Compare commits

..

80 Commits

Author SHA1 Message Date
mbauskar
10fdf5a8c3 Merge branch 'hotfix' 2017-09-04 14:50:30 +05:30
mbauskar
11cf44986b bumped to version 8.10.2 2017-09-04 15:20:30 +06:00
Makarand Bauskar
cf9e986f82 [hotfix] fixed the invalid variable name lead.name (#10648) 2017-09-04 10:25:37 +05:30
Makarand Bauskar
d6922b2de3 [hotfix] lead name should available before creating new customer from quotations (#10642) 2017-09-01 18:45:40 +05:30
mbauskar
4f939b82b6 Merge branch 'hotfix' 2017-08-31 15:31:47 +05:30
mbauskar
2a4328b4f5 bumped to version 8.10.1 2017-08-31 16:01:47 +06:00
tundebabzy
7f8a259beb Fixer Always Fetches Latest Exchange Rate Even When Date is Specified (#10596) (#10597)
* test that confirms the bug. Same test should pass after fix

* make use of correct api url
2017-08-31 14:30:15 +05:30
rohitwaghchaure
56e31d05e9 [Fix] POS customer field is hang while searching customer, make error log if sync has failed (#10607) 2017-08-31 14:19:58 +05:30
krnkris
3c635e219e Rename fr_plan_comptable_général.json to fr_plan_comptable_general.json (#10601) 2017-08-31 14:17:46 +05:30
Makarand Bauskar
de278635a3 [hotfix] fixes for UnicodeDecodeError (#10620) 2017-08-31 13:36:56 +05:30
mbauskar
5096c45dec Merge branch 'master' into hotfix 2017-08-29 20:42:06 +05:30
mbauskar
fd6b371dac Merge branch 'staging' 2017-08-29 20:38:21 +05:30
mbauskar
c0f34f454b bumped to version 8.10.0 2017-08-29 21:08:21 +06:00
tundebabzy
1a947dbf6a Item Name not loaded in Material Request via BOM (#10535) (#10555)
* adds item_name to child table

* adds two new functions to utils:
- first_row_is_empty: to check if first row in child table is empty
- remove_empty_first_row: to remove the empty first row in a child table

* removes empty first row after getting from BOM

* ui test
2017-08-29 18:18:27 +05:30
Faris Ansari
847f9f80c1 Merge pull request #10559 from mntechnique/pos_scanner_hotfix
[Fix] POS Scanner
2017-08-28 16:54:01 +05:30
Faris Ansari
8fbc08f91f Decrease timeout to 400 2017-08-28 16:52:20 +05:30
mbauskar
5d0c4361ab resolved merged conflicts 2017-08-28 11:58:44 +05:30
Revant Nandgaonkar
2558daf6b7 Allow search without keypress enter 2017-08-26 15:52:35 +05:30
Revant Nandgaonkar
2f7cb82ca0 [Fix] POS Scanner
Search item based on key press instead of 1sec wait
Fast Scanning needs this to avoid 1sec delay
2017-08-26 09:58:15 +05:30
mbauskar
dc9744f353 Merge branch 'develop' into staging 2017-08-23 13:19:48 +05:30
Makarand Bauskar
dd8c0febd5 [minor] changed the modified date for bom for rename_bom_update_tool patch (#10509) 2017-08-23 13:17:37 +05:30
mbauskar
06f5ae0e78 Merge branch 'master' into develop 2017-08-23 13:06:43 +05:30
mbauskar
b69ec059fe Merge branch 'master' into develop 2017-08-22 20:22:24 +05:30
rohitwaghchaure
7379e4e5de Merge pull request #10195 from nabinhait/auto_update_bom_cost
Update BOM cost in all BOMs based on latest rm rate
2017-08-22 19:14:53 +05:30
Nabin Hait
bb326f2bbd Chart of accounts for Taiwan (#10435) 2017-08-22 19:07:42 +05:30
Nabin Hait
34c218b2de Minor improvements based on skip_transfer (#10457) 2017-08-22 19:07:16 +05:30
Nabin Hait
382f5eb1b1 Run sales/purchase register for one month by default (#10493) 2017-08-22 19:06:21 +05:30
Doridel Cahanap
a6a93cbe06 [Fix] Request for Quotation Portal Title (#10489) 2017-08-22 18:39:38 +05:30
Vishal Dhayagude
a1637d8343 [UI Test] UI test for Sales Invoice with Payment Entry (#10483)
* [UI Test] UI test for Sales Invoice with Payment Entry

* Update test_purchase_order_receipt.js
2017-08-22 18:33:17 +05:30
Utkarsh Goswami
5cf3bdd593 Travis fix for purchase order receipt (#10498) 2017-08-22 17:39:06 +05:30
mbauskar
3b3ab4d574 Merge branch 'master' into develop 2017-08-22 15:42:10 +05:30
mbauskar
7d9452f4e4 Merge branch 'master' into develop 2017-08-22 12:03:47 +05:30
Nabin Hait
6c6e45157b Fixed test case for replace bom 2017-08-22 10:49:58 +05:30
Nabin Hait
52cc08dd2d Test case added for replacing BOM 2017-08-22 10:49:57 +05:30
Nabin Hait
adbf8adfb9 Update BOM cost in all BOMs based on latest rm rate 2017-08-22 10:49:57 +05:30
Ameya Shenoy
c87c1dbbbf converted production tests to INR from USD (#10472) 2017-08-21 14:10:04 +05:30
Rushabh Mehta
575ab3ab70 [docs] for print style (#10452) 2017-08-21 12:24:28 +05:30
mbauskar
62f0722325 resolved merge conflicts 2017-08-21 08:58:42 +05:30
Zarrar
196b491ac4 [ui test ] Travis failing fix (#10468)
* Value in assertion was wrong

* Update test_purchase_order_receipt.js
2017-08-21 08:07:42 +05:30
KanchanChauhan
dd351c585a [Minor] Title added to rfq web view (#10454) 2017-08-20 11:00:43 +05:30
Vishal Dhayagude
8fd5b325e0 [UI Test] travis.yml modified for fresh UI Test (#10446)
* [UI Test] travis.yml modified for fresh UI Test

* [fix] travis

* Update test_production_order.js

* Update test_production_order.js

* Update test_purchase_order_receipt.js

* Update tests.txt

* Update test_purchase_order_receipt.js
2017-08-20 10:59:48 +05:30
Vishal Dhayagude
592e8c2e77 [UI Test] UI Test added for Stock Reconciliation (#10432)
* [UI Test] UI Test added for Stock Reconciliation

* [fix] Codacy
2017-08-18 15:01:20 +05:30
Utkarsh Goswami
5a27aead06 Test for Process Payroll (#10447) 2017-08-18 13:12:53 +05:30
Utkarsh Goswami
ca63cc6439 [UI Test Recruitment] To test Recruitment in HR module (#10441)
* Tests for Recruitment

* Codacy fix
2017-08-18 11:57:01 +05:30
Vishal Dhayagude
2890fa74a2 [UI Test] UI Test for Purchase Receipt Added (#10434) 2017-08-18 11:55:14 +05:30
Zarrar
780f11ec16 path to test updated (#10438) 2017-08-17 18:36:33 +05:30
Nabin Hait
5b266eff89 Update patches.txt 2017-08-17 14:42:50 +05:30
Nabin Hait
0650d8e155 Merge branch 'bcornwellmott-no_quote' into develop 2017-08-17 12:03:01 +05:30
Ben Cornwell-Mott
ee9f9863ff MORE CODACY 2017-08-17 11:29:11 +05:30
Ben Cornwell-Mott
9727a3fe50 More codacy issues 2017-08-17 11:27:31 +05:30
Rohit Waghchaure
df83191ea0 Set write permission to sales manger for permlevel 1 in Quotation doctype 2017-08-17 11:27:30 +05:30
Ben Cornwell-Mott
13218f7d76 Fixed codacy issues 2017-08-17 11:25:12 +05:30
Ben Cornwell-Mott
bea7d9f919 Added tests 2017-08-17 11:25:12 +05:30
Ben Cornwell-Mott
1b43515160 Codacy fixes 2017-08-17 11:18:49 +05:30
Ben Cornwell-Mott
48058a88e5 Minor cleanup 2017-08-17 11:18:49 +05:30
Ben Cornwell-Mott
f7e42211b9 Added Quote Status to RFQ Suppliers with No Quote 2017-08-17 11:18:49 +05:30
Zarrar
abd3419632 made test less dependent on python test data (#10424) 2017-08-17 11:04:16 +05:30
Shreya Shah
b5ed6823d6 [UI Test] Buying - Create Purchase receipt (#10421)
* Create purchase receipt after submitting the purchase order

* Checks quantity and rate in stock ledger
2017-08-17 11:03:43 +05:30
Vishal Dhayagude
f37eacdee5 [UI Test] Purchase Invoice (#10422)
* [UI Test] Purchase Invoice

* [fix] Travis failed
2017-08-17 11:01:59 +05:30
Zarrar
9eb8680ec9 travis failing issue fix (#10420) 2017-08-16 13:25:31 +05:30
tundebabzy
5fc5b68a49 update multi currency accounting documentation to remove incorrect info (#10404) 2017-08-16 11:41:56 +05:30
Manas Solanki
0371d5a326 new item group filter in the stock ledger report (#10400) 2017-08-16 11:35:04 +05:30
Utkarsh Goswami
44b088c6b3 [UI Test Salary] To test the salary structure and the salary slip (#10407)
* Test for salary structure and salary slip

* Test for salary structure and salary slip

* Test for salary structure and salary slip

* Travis CI fixes

* Updated

* Updated

* travis fixes

* Travis fixes
2017-08-16 11:32:04 +05:30
Shreya Shah
289400d944 [UI Test] Buying module - Multiple tests for Purchase orders (#10414)
* Extended timeout to avoid rare failures

* Get purchase orders with discount on grand total

* Get purchase orders with discount on individual items

* Get purchase orders and calculate taxes

* Added paths
2017-08-16 11:31:34 +05:30
Shreya Shah
f6544e95d4 [UI Tests] Buying Module - Supplier quotations and Purchase orders (#10397)
* Get Supplier Quotation with item wise discount

* Get purchase orders

* Added paths

* Codacy fix
2017-08-14 17:29:09 +05:30
Makarand Bauskar
0973161ae5 [docs] Translate the Schools Assessment section documentation to Spanish (#10398)
* [docs] Translate the Schools app documentation to Spanish

* [docs] Translate the Schools Student section documentation to Spanish

* [docs] Translate the Schools SETUP section documentation to Spanish

* [docs] Translate the Schools ADMISSION section documentation to Spanish

* [docs] Translate the Schools FEES section documentation to Spanish

* [docs] Translate the Schools SCHEDULE section documentation to Spanish

* [docs] Translate the Schools Assessment section documentation to Spanish
2017-08-14 14:55:48 +05:30
mbauskar
4ca3e8f70a Merge branch 'master' into develop 2017-08-14 12:33:55 +05:30
Vishal Dhayagude
7186131d65 [UI Test] sales invoice (#10394)
* [UI Test] Sales Invoice

* [UI Test] Sales Invoice
2017-08-14 12:22:04 +05:30
Manas Solanki
a5cb9ae8bd send email via the background jobs (#10374) 2017-08-14 09:50:15 +05:30
mbauskar
2fa8af3b02 Merge branch 'master' into develop 2017-08-14 09:31:01 +05:30
Shreya Shah
67e2ef30c4 [UI test] Buying module - Get Supplier Quotations (#10375)
* Get quotations for Suppliers

* Calculate taxes and charges for Supplier quotations

* Added paths for tests

* Codacy fix

* Improvised the page route function
2017-08-14 09:17:00 +05:30
Vishal Dhayagude
22baba2cff [UI TEST] Test added for Delivery Note (#10376) 2017-08-11 17:17:30 +05:30
Faris Ansari
7273cb7f54 Track changes in Account doctype (#10373) 2017-08-11 16:19:28 +05:30
Vishal Dhayagude
4157b64776 [UI Test] Multiple UI Test for Stock Entry added (#10354) 2017-08-11 12:06:16 +05:30
Shreya Shah
9e30969243 Fetching items from material requests doctype (#10363) 2017-08-11 12:02:35 +05:30
Rushabh Mehta
dbb5154f37 Fixes in Order / Quotation (#10361)
* Additions in Order Page for Sidebar Menu with "Order" page route

* Adjust Columns in order_taxes.html to avoid number breaks for more precisions

* Fields additions in transaction_row.html

* [fix] style for order pages, indicator for quotation etc

* [fix] style for order pages, indicator for quotation etc

* [test] add timeout
2017-08-10 21:06:09 +05:30
Shreya Shah
5ae39ae79a Get Quotation requests and send emails to suppliers (#10356) 2017-08-10 16:20:47 +05:30
Manas Solanki
a854ea00a5 mark holiday in the employee monthly attendance sheet (#10349) 2017-08-10 11:20:58 +05:30
Manas Solanki
e97f587411 send the email via the background worker in the payment request (#10350) 2017-08-10 11:17:38 +05:30
Rushabh Mehta
17e5f4132c [tests] less verbose logs 2017-08-10 11:03:26 +05:30
159 changed files with 3731 additions and 480 deletions

View File

@@ -53,6 +53,9 @@ before_script:
script:
- set -e
- bench --verbose run-tests
- bench run-tests
- sleep 5
- bench --verbose run-ui-tests --app erpnext
- bench reinstall --yes
- bench execute erpnext.setup.setup_wizard.utils.complete
- bench execute erpnext.setup.utils.enable_all_roles_and_domains
- bench run-ui-tests --app erpnext

View File

@@ -4,7 +4,7 @@ import inspect
import frappe
from erpnext.hooks import regional_overrides
__version__ = '8.9.2'
__version__ = '8.10.2'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -13,6 +13,7 @@
"editable_grid": 0,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -42,6 +43,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -70,6 +72,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -100,6 +103,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -130,6 +134,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -161,6 +166,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -190,6 +196,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -219,6 +226,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -250,6 +258,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -278,6 +287,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -309,6 +319,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -341,6 +352,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -372,6 +384,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -404,6 +417,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -433,6 +447,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -461,6 +476,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -489,6 +505,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -528,7 +545,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-04-21 17:22:41.150984",
"modified": "2017-08-11 15:28:35.855809",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
@@ -641,6 +658,6 @@
"search_fields": "",
"show_name_in_global_search": 1,
"sort_order": "ASC",
"track_changes": 0,
"track_changes": 1,
"track_seen": 0
}

View File

@@ -78,6 +78,7 @@ def get_chart(chart_template, existing_company=None):
for folder in folders:
path = os.path.join(os.path.dirname(__file__), folder)
for fname in os.listdir(path):
fname = frappe.as_unicode(fname)
if fname.endswith(".json"):
with open(os.path.join(path, fname), "r") as f:
chart = f.read()
@@ -105,6 +106,7 @@ def get_charts_for_country(country):
path = os.path.join(os.path.dirname(__file__), folder)
for fname in os.listdir(path):
fname = frappe.as_unicode(fname)
if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
with open(os.path.join(path, fname), "r") as f:
_get_chart_name(f.read())

View File

@@ -0,0 +1,722 @@
{
"country_code": "tw",
"name": "Taiwan - Chart of Accounts",
"tree": {
"1-\u8cc7\u7522": {
"11~12-\u6d41\u52d5\u8cc7\u7522": {
"111-\u73fe\u91d1\u53ca\u7d04\u7576\u73fe\u91d1": {
"1111-\u5eab\u5b58\u73fe\u91d1": {
"account_type": "Cash"
},
"1112-\u96f6\u7528\u91d1/\u9031\u8f49\u91d1": {
"account_type": "Cash"
},
"1113-\u9280\u884c\u5b58\u6b3e": {
"account_type": "Bank",
"\u4e2d\u570b\u4fe1\u8a17": {
"account_type": "Bank"
},
"\u53f0\u5317\u5bcc\u90a6": {
"account_type": "Bank"
}
},
"1116-\u5728\u9014\u73fe\u91d1": {
"account_type": "Cash"
},
"1117-\u7d04\u7576\u73fe\u91d1": {
"account_type": "Cash"
},
"1118-\u5176\u4ed6\u73fe\u91d1\u53ca\u7d04\u7576\u73fe\u91d1": {
"account_type": "Cash"
},
"account_type": "Cash"
},
"112-\u77ed\u671f\u6295\u8cc7": {
"1121-\u77ed\u671f\u6295\u8cc7 \u2014\u80a1\u7968": {}
},
"113-\u61c9\u6536\u7968\u64da": {
"1131-\u61c9\u6536\u7968\u64da": {
"account_type": "Receivable"
},
"1132-\u61c9\u6536\u7968\u64da\u8cbc\u73fe ": {
"account_type": "Receivable"
},
"1138-\u5176\u4ed6\u61c9\u6536\u7968\u64da ": {
"account_type": "Receivable"
},
"1139-\u5099\u62b5\u5446\u5e33 \uff0d\u61c9\u6536\u7968\u64da ": {
"account_type": "Receivable"
},
"account_type": "Receivable"
},
"114-\u61c9\u6536\u5e33\u6b3e": {
"1141-\u61c9\u6536\u5e33\u6b3e ": {
"account_type": "Receivable"
},
"1142-\u61c9\u6536\u5206\u671f\u5e33\u6b3e ": {
"account_type": "Receivable"
},
"1149-\u5099\u62b5\u5446\u5e33 \uff0d\u61c9\u6536\u5e33\u6b3e ": {
"account_type": "Receivable"
},
"account_type": "Receivable"
},
"118-\u5176\u4ed6\u61c9\u6536\u6b3e": {
"1184-\u61c9\u6536\u6536\u76ca": {
"account_type": "Receivable"
},
"1185-\u61c9\u6536\u9000\u7a05\u6b3e": {
"account_type": "Receivable"
},
"1189-\u5099\u62b5\u5446\u5e33 \u2014 \u5176\u4ed6\u61c9\u6536\u6b3e ": {
"account_type": "Receivable"
},
"account_type": "Receivable"
},
"121~122-\u5b58\u8ca8": {
"1219-\u5099\u62b5\u5b58\u8ca8\u8dcc\u50f9\u640d\u5931": {},
"1229-\u5099\u62b5\u5b58\u8ca8\u8dcc\u50f9\u640d\u5931": {},
"account_type": "Stock",
"is_group": 1
},
"125-\u9810\u4ed8\u8cbb\u7528": {
"1251-\u9810\u4ed8\u85aa\u8cc7": {},
"1252-\u9810\u4ed8\u79df\u91d1": {},
"1253-\u9810\u4ed8\u4fdd\u96aa\u8cbb": {},
"1254-\u7528\u54c1\u76e4\u5b58": {},
"1255-\u9810\u4ed8\u6240\u5f97\u7a05": {},
"1258-\u5176\u4ed6\u9810\u4ed8\u8cbb\u7528": {}
},
"126-\u9810\u4ed8\u6b3e\u9805": {
"1261-\u9810\u4ed8\u8ca8\u6b3e": {},
"1268-\u5176\u4ed6\u9810\u4ed8\u6b3e\u9805": {}
},
"128~129-\u5176\u4ed6\u6d41\u52d5\u8cc7\u7522": {
"1281-\u9032\u9805\u7a05\u984d": {},
"1282-\u7559\u62b5\u7a05\u984d": {},
"1283-\u66ab\u4ed8\u6b3e": {},
"1284-\u4ee3\u4ed8\u6b3e": {},
"1285-\u54e1\u5de5\u501f\u652f": {}
}
},
"13-\u57fa\u91d1\u53ca\u9577\u671f\u6295\u8cc7": {
"131-\u57fa\u91d1": {
"1311-\u511f\u50b5\u57fa\u91d1": {},
"1313-\u610f\u5916\u640d\u5931\u6e96\u5099\u57fa\u91d1": {},
"1314-\u9000\u4f11\u57fa\u91d1": {},
"1318-\u5176\u4ed6\u57fa\u91d1": {}
},
"132-\u9577\u671f\u6295\u8cc7": {
"1321-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7": {},
"1322-\u9577\u671f\u50b5\u5238\u6295\u8cc7": {},
"1323-\u9577\u671f\u4e0d\u52d5\u7522\u6295\u8cc7": {},
"1328-\u5176\u4ed6\u9577\u671f\u6295\u8cc7": {}
}
},
"14~15-\u56fa\u5b9a\u8cc7\u7522": {
"141-\u571f\u5730": {
"1411-\u571f\u5730": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"142-\u571f\u5730\u6539\u826f\u7269": {
"1421-\u571f\u5730\u6539\u826f\u7269": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"143-\u623f\u5c4b\u53ca\u5efa\u7269": {
"1431-\u623f\u5c4b\u53ca\u5efa\u7269": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"144~146-\u6a5f(\u5668)\u5177\u53ca\u8a2d\u5099": {
"1441-\u6a5f(\u5668)\u5177": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"151-\u79df\u8cc3\u8cc7\u7522": {
"1511-\u79df\u8cc3\u8cc7\u7522": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"152-\u79df\u8cc3\u6b0a\u76ca\u6539\u826f": {
"1521-\u79df\u8cc3\u6b0a\u76ca\u6539\u826f": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"156-\u672a\u5b8c\u5de5\u7a0b\u53ca\u9810\u4ed8\u8cfc\u7f6e\u8a2d\u5099\u6b3e": {
"1561-\u672a\u5b8c\u5de5\u7a0b": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"158-\u96dc\u9805\u56fa\u5b9a\u8cc7\u7522": {
"1581-\u96dc\u9805\u56fa\u5b9a\u8cc7\u7522": {
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"account_type": "Fixed Asset"
},
"16-\u905e\u8017\u8cc7\u7522": {
"161-\u905e\u8017\u8cc7\u7522": {
"is_group": 1
}
},
"17-\u7121\u5f62\u8cc7\u7522": {
"171-\u5546\u6a19\u6b0a": {
"1711-\u5546\u6a19\u6b0a": {}
},
"172-\u5c08\u5229\u6b0a": {
"1721-\u5c08\u5229\u6b0a": {}
},
"176-\u5546\u8b7d": {
"1761-\u5546\u8b7d": {}
},
"177-\u958b\u8fa6\u8cbb": {
"1771-\u958b\u8fa6\u8cbb": {}
},
"178-\u5176\u4ed6\u7121\u5f62\u8cc7\u7522": {
"1781-\u905e\u5ef6\u9000\u4f11\u91d1\u6210\u672c": {}
}
},
"18-\u5176\u4ed6\u8cc7\u7522": {
"181-\u905e\u5ef6\u8cc7\u7522": {
"1811-\u50b5\u5238\u767c\u884c\u6210\u672c": {},
"1812-\u9577\u671f\u9810\u4ed8\u79df\u91d1": {},
"1813-\u9577\u671f\u9810\u4ed8\u4fdd\u96aa\u8cbb": {},
"1814-\u905e\u5ef6\u6240\u5f97\u7a05\u8cc7\u7522": {},
"1815-\u9810\u4ed8\u9000\u4f11\u91d1": {},
"1818-\u5176\u4ed6\u905e\u5ef6\u8cc7\u7522": {}
},
"182-\u9592\u7f6e\u8cc7\u7522": {
"1821-\u9592\u7f6e\u8cc7\u7522": {}
},
"184-\u9577\u671f\u61c9\u6536\u7968\u64da\u53ca\u6b3e\u9805\u8207\u50ac\u6536\u5e33\u6b3e": {
"1841-\u9577\u671f\u61c9\u6536\u7968\u64da": {
"account_type": "Receivable"
},
"1842-\u9577\u671f\u61c9\u6536\u5e33\u6b3e": {
"account_type": "Receivable"
},
"1843-\u50ac\u6536\u5e33\u6b3e": {
"account_type": "Receivable"
},
"1848-\u5176\u4ed6\u9577\u671f\u61c9\u6536\u6b3e\u9805": {
"account_type": "Receivable"
},
"1849-\u5099\u62b5\u5446\u5e33\u2014\u9577\u671f\u61c9\u6536\u7968\u64da\u53ca\u6b3e\u9805\u8207\u50ac\u6536\u5e33\u6b3e": {
"account_type": "Receivable"
},
"account_type": "Receivable"
},
"185-\u51fa\u79df\u8cc7\u7522": {
"1851-\u51fa\u79df\u8cc7\u7522": {},
"1858-\u51fa\u79df\u8cc7\u7522 \u2014\u91cd\u4f30\u589e\u503c": {},
"1859-\u7d2f\u7a4d\u6298\u820a \u2014\u51fa\u79df\u8cc7\u7522": {
"account_type": "Accumulated Depreciation"
}
},
"186-\u5b58\u51fa\u4fdd\u8b49\u91d1": {
"1861-\u5b58\u51fa\u4fdd\u8b49\u91d1": {}
},
"188-\u96dc\u9805\u8cc7\u7522": {
"1881-\u53d7\u9650\u5236\u5b58\u6b3e": {},
"1888-\u96dc\u9805\u8cc7\u7522 \u2014\u5176\u4ed6": {}
}
},
"Temporary Accounts": {
"Temporary Opening": {
"account_type": "Temporary"
},
"account_type": "Temporary"
},
"root_type": "Asset"
},
"2-\u8ca0\u50b5": {
"21~22-\u6d41\u52d5\u8ca0\u50b5": {
"211-\u77ed\u671f\u501f\u6b3e": {
"2111-\u9280\u884c\u900f\u652f": {},
"2112-\u9280\u884c\u501f\u6b3e": {}
},
"212-\u61c9\u4ed8\u77ed\u671f\u7968\u5238": {
"2121-\u61c9\u4ed8\u5546\u696d\u672c\u7968": {
"account_type": "Payable"
},
"2122-\u9280\u884c\u627f\u514c\u532f\u7968": {
"account_type": "Payable"
},
"account_type": "Payable"
},
"213-\u61c9\u4ed8\u7968\u64da": {
"2131-\u61c9\u4ed8\u7968\u64da": {
"account_type": "Payable"
},
"account_type": "Payable"
},
"214-\u61c9\u4ed8\u5e33\u6b3e": {
"2141-\u61c9\u4ed8\u5e33\u6b3e": {
"account_type": "Payable"
},
"account_type": "Payable"
},
"216-\u61c9\u4ed8\u6240\u5f97\u7a05": {
"2161-\u61c9\u4ed8\u6240\u5f97\u7a05": {
"account_type": "Tax",
"tax_rate": 5.0
},
"account_type": "Tax",
"tax_rate": 5.0
},
"217-\u61c9\u4ed8\u8cbb\u7528": {
"2171-\u61c9\u4ed8\u85aa\u5de5": {},
"2172-\u61c9\u4ed8\u79df\u91d1": {},
"2173-\u61c9\u4ed8\u5229\u606f": {},
"2174-\u61c9\u4ed8\u71df\u696d\u7a05": {},
"2175-\u61c9\u4ed8\u7a05\u6350 \u2014\u5176\u4ed6": {
"account_type": "Tax",
"tax_rate": 5.0
},
"2178-\u5176\u4ed6\u61c9\u4ed8\u8cbb\u7528": {}
},
"218~219-\u5176\u4ed6\u61c9\u4ed8\u6b3e": {
"2184-\u61c9\u4ed8\u571f\u5730\u623f\u5c4b\u6b3e": {},
"2185-\u61c9\u4ed8\u8a2d\u5099\u6b3e": {},
"2192-\u61c9\u4ed8\u80a1\u5229": {}
},
"226-\u9810\u6536\u6b3e\u9805": {
"2261-\u9810\u6536\u8ca8\u6b3e": {},
"2262-\u9810\u6536\u6536\u5165": {},
"2268-\u5176\u4ed6\u9810\u6536\u6b3e": {}
},
"227-\u4e00\u5e74\u6216\u4e00\u71df\u696d\u9031\u671f\u5167\u5230\u671f\u9577\u671f\u8ca0\u50b5": {
"is_group": 1
},
"228~229-\u5176\u4ed6\u6d41\u52d5\u8ca0\u50b5": {
"2281-\u92b7\u9805\u7a05\u984d": {},
"2283-\u66ab\u6536\u6b3e ": {},
"2284-\u4ee3\u6536\u6b3e": {},
"2285-\u4f30\u8a08\u552e\u5f8c\u670d\u52d9/\u4fdd\u56fa\u8ca0\u50b5": {},
"2291-\u905e\u5ef6\u6240\u5f97\u7a05\u8ca0\u50b5": {},
"2292-\u905e\u5ef6\u514c\u63db\u5229\u76ca": {}
}
},
"23-\u9577\u671f\u8ca0\u50b5": {
"231-\u61c9\u4ed8\u516c\u53f8\u50b5": {
"2311-\u61c9\u4ed8\u516c\u53f8\u50b5": {},
"2319-\u61c9\u4ed8\u516c\u53f8\u50b5\u6ea2(\u6298)\u50f9": {}
},
"232-\u9577\u671f\u501f\u6b3e": {
"2321-\u9577\u671f\u9280\u884c\u501f\u6b3e": {},
"2324-\u9577\u671f\u501f\u6b3e \u2014\u696d\u4e3b": {},
"2325-\u9577\u671f\u501f\u6b3e \u2014\u54e1\u5de5": {},
"2327-\u9577\u671f\u501f\u6b3e \u2014\u95dc\u4fc2\u4eba": {},
"2328-\u9577\u671f\u501f\u6b3e \u2014\u5176\u4ed6": {}
},
"233-\u9577\u671f\u61c9\u4ed8\u7968\u64da\u53ca\u6b3e\u9805": {
"2331-\u9577\u671f\u61c9\u4ed8\u7968\u64da": {
"account_type": "Payable"
},
"2332-\u9577\u671f\u61c9\u4ed8\u5e33\u6b3e": {
"account_type": "Payable"
},
"2333-\u9577\u671f\u61c9\u4ed8\u79df\u8cc3\u8ca0\u50b5": {
"account_type": "Payable"
},
"account_type": "Payable"
},
"234-\u4f30\u8a08\u61c9\u4ed8\u571f\u5730\u589e\u503c\u7a05": {
"2341-\u4f30\u8a08\u61c9\u4ed8\u571f\u5730\u589e\u503c\u7a05": {}
},
"235-\u61c9\u8a08\u9000\u4f11\u91d1\u8ca0\u50b5": {
"2351-\u61c9\u8a08\u9000\u4f11\u91d1\u8ca0\u50b5": {}
},
"238-\u5176\u4ed6\u9577\u671f\u8ca0\u50b5": {
"2388-\u5176\u4ed6\u9577\u671f\u8ca0\u50b5\u2014\u5176\u4ed6": {}
}
},
"28-\u5176\u4ed6\u8ca0\u50b5": {
"281-\u905e\u5ef6\u8ca0\u50b5": {
"2811-\u905e\u5ef6\u6536\u5165": {},
"2814-\u905e\u5ef6\u6240\u5f97\u7a05\u8ca0\u50b5": {},
"2818-\u5176\u4ed6\u905e\u5ef6\u8ca0\u50b5": {}
},
"286-\u5b58\u5165\u4fdd\u8b49\u91d1": {
"2861-\u5b58\u5165\u4fdd\u8b49\u91d1": {}
},
"288-\u96dc\u9805\u8ca0\u50b5": {
"2888-\u96dc\u9805\u8ca0\u50b5 \u2014\u5176\u4ed6": {}
}
},
"Stock Received But Not Billed": {
"account_type": "Stock Received But Not Billed"
},
"root_type": "Liability"
},
"3-\u696d\u4e3b\u6b0a\u76ca": {
"31-\u8cc7\u672c": {
"311-\u8cc7\u672c\uff08\u80a1\u672c\uff09 ": {
"3111-\u666e\u901a\u80a1\u80a1\u672c": {},
"3112-\u7279\u5225\u80a1\u80a1\u672c": {},
"3113-\u9810\u6536\u80a1\u672c": {},
"3114-\u5f85\u5206\u914d\u80a1\u7968\u80a1\u5229": {},
"3115-\u8cc7\u672c": {}
}
},
"32-\u8cc7\u672c\u516c\u7a4d": {
"321-\u80a1\u7968\u6ea2\u50f9": {
"3211-\u666e\u901a\u80a1\u80a1\u7968\u6ea2\u50f9": {},
"3212-\u7279\u5225\u80a1\u80a1\u7968\u6ea2\u50f9": {}
},
"323-\u8cc7\u7522\u91cd\u4f30\u589e\u503c\u6e96\u5099": {
"3231-\u8cc7\u7522\u91cd\u4f30\u589e\u503c\u6e96\u5099": {}
},
"324-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u516c\u7a4d": {
"3241-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u516c\u7a4d": {}
},
"325-\u5408\u4f75\u516c\u7a4d": {
"3251-\u5408\u4f75\u516c\u7a4d": {}
},
"326-\u53d7\u8d08\u516c\u7a4d": {
"3261-\u53d7\u8d08\u516c\u7a4d": {}
},
"328-\u5176\u4ed6\u8cc7\u672c\u516c\u7a4d": {
"3281-\u6b0a\u76ca\u6cd5\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u8cc7\u672c\u516c\u7a4d": {},
"3282-\u8cc7\u672c\u516c\u7a4d\u2014 \u5eab\u85cf\u80a1\u7968\u4ea4\u6613": {}
}
},
"33-\u4fdd\u7559\u76c8\u9918(\u7d2f\u7a4d\u8667\u640d)": {
"331-\u6cd5\u5b9a\u76c8\u9918\u516c\u7a4d": {
"3311-\u6cd5\u5b9a\u76c8\u9918\u516c\u7a4d": {}
},
"332-\u7279\u5225\u76c8\u9918\u516c\u7a4d": {
"3321-\u610f\u5916\u640d\u5931\u6e96\u5099": {},
"3322-\u6539\u826f\u64f4\u5145\u6e96\u5099": {},
"3323-\u511f\u50b5\u6e96\u5099": {},
"3328-\u5176\u4ed6\u7279\u5225\u76c8\u9918\u516c\u7a4d": {}
},
"335-\u672a\u5206\u914d\u76c8\u9918(\u7d2f\u7a4d\u8667\u640d) ": {
"is_group": 1
}
},
"34-\u6b0a\u76ca\u8abf\u6574": {
"341-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {
"3411-\u9577\u671f\u80a1\u6b0a\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {}
},
"342-\u7d2f\u7a4d\u63db\u7b97\u8abf\u6574\u6578": {
"3421-\u7d2f\u7a4d\u63db\u7b97\u8abf\u6574\u6578": {}
},
"343-\u672a\u8a8d\u5217\u70ba\u9000\u4f11\u91d1\u6210\u672c\u4e4b\u6de8\u640d\u5931": {
"3431-\u672a\u8a8d\u5217\u70ba\u9000\u4f11\u91d1\u6210\u672c\u4e4b\u6de8\u640d\u5931": {}
}
},
"35-\u5eab\u85cf\u80a1": {
"351-\u5eab\u85cf\u80a1": {
"3511-\u5eab\u85cf\u80a1": {}
}
},
"36-\u5c11\u6578\u80a1\u6b0a": {
"361-\u5c11\u6578\u80a1\u6b0a": {
"3611-\u5c11\u6578\u80a1\u6b0a": {}
}
},
"root_type": "Equity"
},
"4-\u71df\u696d\u6536\u5165": {
"41-\u92b7\u8ca8\u6536\u5165": {
"411-\u92b7\u8ca8\u6536\u5165": {
"4111-\u92b7\u8ca8\u6536\u5165": {},
"4112-\u5206\u671f\u4ed8\u6b3e\u92b7\u8ca8\u6536\u5165": {}
},
"417-\u92b7\u8ca8\u9000\u56de": {
"4171-\u92b7\u8ca8\u9000\u56de": {}
},
"419-\u92b7\u8ca8\u6298\u8b93": {
"4191-\u92b7\u8ca8\u6298\u8b93": {}
}
},
"46-\u52de\u52d9\u6536\u5165": {
"461-\u52de\u52d9\u6536\u5165": {
"4611-\u52de\u52d9\u6536\u5165": {}
}
},
"47-\u696d\u52d9\u6536\u5165": {
"471-\u696d\u52d9\u6536\u5165": {
"4711-\u696d\u52d9\u6536\u5165": {}
}
},
"48-\u5176\u4ed6\u71df\u696d\u6536\u5165": {
"488-\u5176\u4ed6\u71df\u696d\u6536\u5165\u2014\u5176\u4ed6": {
"4888-\u5176\u4ed6\u71df\u696d\u6536\u5165\u2014\u5176\u4ed6": {}
}
},
"root_type": "Income"
},
"5-\u71df\u696d\u6210\u672c": {
"51-\u92b7\u8ca8\u6210\u672c": {
"511-\u92b7\u8ca8\u6210\u672c": {
"5111-\u92b7\u8ca8\u6210\u672c": {
"account_type": "Cost of Goods Sold"
},
"5112-\u5206\u671f\u4ed8\u6b3e\u92b7\u8ca8\u6210\u672c": {
"account_type": "Cost of Goods Sold"
},
"account_type": "Cost of Goods Sold"
},
"512-\u9032\u8ca8": {
"5121-\u9032\u8ca8": {},
"5122-\u9032\u8ca8\u8cbb\u7528": {},
"5123-\u9032\u8ca8\u9000\u51fa": {},
"5124-\u9032\u8ca8\u6298\u8b93": {}
},
"513-\u9032\u6599": {
"5131-\u9032\u6599": {},
"5132-\u9032\u6599\u8cbb\u7528": {},
"5133-\u9032\u6599\u9000\u51fa": {},
"5134-\u9032\u6599\u6298\u8b93": {}
},
"514-\u76f4\u63a5\u4eba\u5de5": {
"5141-\u76f4\u63a5\u4eba\u5de5": {}
},
"515~518-\u88fd\u9020\u8cbb\u7528": {
"5151-\u9593\u63a5\u4eba\u5de5": {},
"5152-\u79df\u91d1\u652f\u51fa": {},
"5153-\u6587\u5177\u7528\u54c1": {},
"5154-\u65c5\u8cbb": {},
"5155-\u904b\u8cbb": {},
"5156-\u90f5\u96fb\u8cbb": {},
"5157-\u4fee\u7e55\u8cbb": {},
"5158-\u5305\u88dd\u8cbb": {},
"5161-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
"5162-\u4fdd\u96aa\u8cbb": {},
"5163-\u52a0\u5de5\u8cbb": {},
"5166-\u7a05\u6350": {
"account_type": "Tax",
"tax_rate": 5.0
},
"5168-\u6298\u820a ": {
"account_type": "Depreciation"
},
"5169-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
"5172-\u4f19\u98df\u8cbb": {},
"5173-\u8077\u5de5\u798f\u5229": {},
"5176-\u8a13\u7df4\u8cbb": {},
"5177-\u9593\u63a5\u6750\u6599": {},
"5188-\u5176\u4ed6\u88fd\u9020\u8cbb\u7528": {}
},
"Expenses Included In Valuation": {
"account_type": "Expenses Included In Valuation"
},
"account_type": "Cost of Goods Sold"
},
"56-\u52de\u52d9\u6210\u672c\u88fd": {
"561-\u52de\u52d9\u6210\u672c": {
"5611-\u52de\u52d9\u6210\u672c": {}
}
},
"57-\u696d\u52d9\u6210\u672c": {
"571-\u696d\u52d9\u6210\u672c": {
"5711-\u696d\u52d9\u6210\u672c": {}
}
},
"58-\u5176\u4ed6\u71df\u696d\u6210\u672c": {
"588-\u5176\u4ed6\u71df\u696d\u6210\u672c\u2014\u5176\u4ed6 ": {
"5888-\u5176\u4ed6\u71df\u696d\u6210\u672c\u2014\u5176\u4ed6": {}
}
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
},
"root_type": "Expense"
},
"6-\u71df\u696d\u8cbb\u7528": {
"61-\u63a8\u92b7\u8cbb\u7528": {
"615~618-\u63a8\u92b7\u8cbb\u7528": {
"6151-\u85aa\u8cc7\u652f\u51fa": {},
"6152-\u79df\u91d1\u652f\u51fa": {},
"6153-\u6587\u5177\u7528\u54c1": {},
"6154-\u65c5\u8cbb": {},
"6155-\u904b\u8cbb": {},
"6156-\u90f5\u96fb\u8cbb": {},
"6157-\u4fee\u7e55\u8cbb": {},
"6159-\u5ee3\u544a\u8cbb": {},
"6161-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
"6162-\u4fdd\u96aa\u8cbb": {},
"6164-\u4ea4\u969b\u8cbb": {},
"6165-\u6350\u8d08": {},
"6166-\u7a05\u6350": {
"account_type": "Tax",
"tax_rate": 5.0
},
"6167-\u5446\u5e33\u640d\u5931": {},
"6168-\u6298\u820a ": {
"account_type": "Depreciation"
},
"6169-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
"6172-\u4f19\u98df\u8cbb": {},
"6173-\u8077\u5de5\u798f\u5229": {},
"6175-\u4f63\u91d1\u652f\u51fa": {},
"6176-\u8a13\u7df4\u8cbb": {},
"6188-\u5176\u4ed6\u63a8\u92b7\u8cbb\u7528": {}
}
},
"62-\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {
"625~628-\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {
"6251-\u85aa\u8cc7\u652f\u51fa": {},
"6252-\u79df\u91d1\u652f\u51fa": {},
"6253-\u6587\u5177\u7528\u54c1": {},
"6254-\u65c5\u8cbb": {},
"6255-\u904b\u8cbb": {},
"6256-\u90f5\u96fb\u8cbb": {},
"6257-\u4fee\u7e55\u8cbb": {},
"6259-\u5ee3\u544a\u8cbb": {},
"6261-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
"6262-\u4fdd\u96aa\u8cbb": {},
"6264-\u4ea4\u969b\u8cbb": {},
"6265-\u6350\u8d08": {},
"6266-\u7a05\u6350": {
"account_type": "Tax",
"tax_rate": 5.0
},
"6267-\u5446\u5e33\u640d\u5931": {},
"6268-\u6298\u820a": {
"account_type": "Depreciation"
},
"6269-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
"6271-\u5916\u92b7\u640d\u5931": {},
"6272-\u4f19\u98df\u8cbb": {},
"6273-\u8077\u5de5\u798f\u5229": {},
"6274-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {},
"6275-\u4f63\u91d1\u652f\u51fa": {},
"6276-\u8a13\u7df4\u8cbb": {},
"6278-\u52de\u52d9\u8cbb": {},
"6288-\u5176\u4ed6\u7ba1\u7406\u53ca\u7e3d\u52d9\u8cbb\u7528": {}
}
},
"63-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {
"635~638-\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {
"6351-\u85aa\u8cc7\u652f\u51fa": {},
"6352-\u79df\u91d1\u652f\u51fa": {},
"6353-\u6587\u5177\u7528\u54c1": {},
"6354-\u65c5\u8cbb": {},
"6355-\u904b\u8cbb": {},
"6356-\u90f5\u96fb\u8cbb": {},
"6357-\u4fee\u7e55\u8cbb": {},
"6361-\u6c34\u96fb\u74e6\u65af\u8cbb": {},
"6362-\u4fdd\u96aa\u8cbb": {},
"6364-\u4ea4\u969b\u8cbb": {},
"6366-\u7a05\u6350": {
"account_type": "Tax",
"tax_rate": 5.0
},
"6368-\u6298\u820a": {
"account_type": "Depreciation"
},
"6369-\u5404\u9805\u8017\u7aed\u53ca\u6524\u63d0": {},
"6372-\u4f19\u98df\u8cbb": {},
"6373-\u8077\u5de5\u798f\u5229": {},
"6376-\u8a13\u7df4\u8cbb": {},
"6378-\u5176\u4ed6\u7814\u7a76\u767c\u5c55\u8cbb\u7528": {}
}
},
"root_type": "Expense"
},
"7-\u71df\u696d\u5916\u6536\u5165\u53ca\u8cbb\u7528": {
"71~74-\u71df\u696d\u5916\u6536\u5165": {
"711-\u5229\u606f\u6536\u5165": {
"7111-\u5229\u606f\u6536\u5165": {}
},
"712-\u6295\u8cc7\u6536\u76ca": {
"7121-\u6b0a\u76ca\u6cd5\u8a8d\u5217\u4e4b\u6295\u8cc7\u6536\u76ca": {},
"7122-\u80a1\u5229\u6536\u5165": {},
"7123-\u77ed\u671f\u6295\u8cc7\u5e02\u50f9\u56de\u5347\u5229\u76ca": {}
},
"713-\u514c\u63db\u5229\u76ca": {
"7131-\u514c\u63db\u5229\u76ca": {}
},
"714-\u8655\u5206\u6295\u8cc7\u6536\u76ca": {
"7141-\u8655\u5206\u6295\u8cc7\u6536\u76ca": {}
},
"715-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u6536\u5165": {
"7151-\u8655\u5206\u8cc7\u7522\u6ea2\u50f9\u6536\u5165": {}
},
"748-\u5176\u4ed6\u71df\u696d\u5916\u6536\u5165": {
"7481-\u6350\u8d08\u6536\u5165": {},
"7482-\u79df\u91d1\u6536\u5165": {},
"7483-\u4f63\u91d1\u6536\u5165": {},
"7484-\u51fa\u552e\u4e0b\u8173\u53ca\u5ee2\u6599\u6536\u5165": {},
"7485-\u5b58\u8ca8\u76e4\u76c8": {},
"7486-\u5b58\u8ca8\u8dcc\u50f9\u56de\u5347\u5229\u76ca": {},
"7487-\u58de\u5e33\u8f49\u56de\u5229\u76ca": {},
"7488-\u5176\u4ed6\u71df\u696d\u5916\u6536\u5165\u2014\u5176\u4ed6": {}
}
},
"75~78-\u71df\u696d\u5916\u8cbb\u7528": {
"751-\u5229\u606f\u8cbb\u7528": {
"7511-\u5229\u606f\u8cbb\u7528": {}
},
"752-\u6295\u8cc7\u640d\u5931": {
"7521-\u6b0a\u76ca\u6cd5\u8a8d\u5217\u4e4b\u6295\u8cc7\u640d\u5931": {},
"7523-\u77ed\u671f\u6295\u8cc7\u672a\u5be6\u73fe\u8dcc\u50f9\u640d\u5931": {}
},
"753-\u514c\u63db\u640d\u5931": {
"7531-\u514c\u63db\u640d\u5931": {}
},
"754-\u8655\u5206\u6295\u8cc7\u640d\u5931": {
"7541-\u8655\u5206\u6295\u8cc7\u640d\u5931": {}
},
"755-\u8655\u5206\u8cc7\u7522\u640d\u5931": {
"7551-\u8655\u5206\u8cc7\u7522\u640d\u5931 ": {}
},
"788-\u5176\u4ed6\u71df\u696d\u5916\u8cbb\u7528": {
"7881-\u505c\u5de5\u640d\u5931": {},
"7882-\u707d\u5bb3\u640d\u5931": {},
"7885-\u5b58\u8ca8\u76e4\u640d": {},
"7886-\u5b58\u8ca8\u8dcc\u50f9\u53ca\u5446\u6eef\u640d\u5931": {},
"7888-\u5176\u4ed6\u71df\u696d\u5916\u8cbb\u7528\u2014\u5176\u4ed6": {}
}
},
"root_type": "Income"
},
"8-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca)": {
"81-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca)": {
"811-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca) ": {
"8111-\u6240\u5f97\u7a05\u8cbb\u7528(\u5229\u76ca) ": {}
}
},
"root_type": "Expense"
},
"9-\u975e\u7d93\u5e38\u71df\u696d\u640d\u76ca": {
"91-\u505c\u696d\u90e8\u9580\u640d\u76ca": {
"911-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u505c\u696d\u524d\u71df\u696d\u640d\u76ca": {
"9111-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u505c\u696d\u524d\u71df\u696d\u640d\u76ca": {}
},
"912-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u8655\u5206\u640d\u76ca": {
"9121-\u505c\u696d\u90e8\u9580\u640d\u76ca\u2014\u8655\u5206\u640d\u76ca": {}
}
},
"92-\u975e\u5e38\u640d\u76ca": {
"921-\u975e\u5e38\u640d\u76ca": {
"9211-\u975e\u5e38\u640d\u76ca": {}
}
},
"93-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {
"931-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {
"9311-\u6703\u8a08\u539f\u5247\u8b8a\u52d5\u7d2f\u7a4d\u5f71\u97ff\u6578": {}
}
},
"94-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {
"941-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {
"9411-\u5c11\u6578\u80a1\u6b0a\u6de8\u5229": {}
}
},
"root_type": "Expense"
}
}
}

View File

@@ -0,0 +1,43 @@
QUnit.module('Purchaes Invoice');
QUnit.test("test purchase invoice", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Invoice', [
{supplier: 'Test Supplier'},
{items: [
[
{'qty': 5},
{'item_code': 'Test Product 1'},
{'rate':100},
]
]},
{update_stock:1},
{supplier_address: 'Test1-Billing'},
{contact_person: 'Contact 3-Test Supplier'},
{taxes_and_charges: 'TEST In State GST'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
},
() => cur_frm.save(),
() => {
// get_item_details
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
// get tax details
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
// get tax account head details
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
// grand_total Calculated
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,26 @@
QUnit.module('Sales Taxes and Charges Template');
QUnit.test("test sales taxes and charges template", function(assert) {
assert.expect(1);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Taxes and Charges Template', [
{title: "TEST In State GST"},
{taxes:[
[
{charge_type:"On Net Total"},
{account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
],
[
{charge_type:"On Net Total"},
{account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
]
]}
]);
},
() => {assert.ok(cur_frm.doc.title=='TEST In State GST');},
() => done()
]);
});

View File

@@ -320,8 +320,7 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}):
si_doc.set_posting_time = 1
si_doc.customer = get_customer_id(doc)
si_doc.due_date = doc.get('posting_date')
submit_invoice(si_doc, name, doc)
name_list.append(name)
name_list = submit_invoice(si_doc, name, doc, name_list)
else:
name_list.append(name)
@@ -475,19 +474,29 @@ def validate_item(doc):
frappe.db.commit()
def submit_invoice(si_doc, name, doc):
def submit_invoice(si_doc, name, doc, name_list):
try:
si_doc.insert()
si_doc.submit()
frappe.db.commit()
name_list.append(name)
except Exception as e:
if frappe.message_log: frappe.message_log.pop()
frappe.db.rollback()
save_invoice(e, si_doc, name)
frappe.log_error(frappe.get_traceback())
name_list = save_invoice(e, si_doc, name, name_list)
def save_invoice(e, si_doc, name):
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
si_doc.docstatus = 0
si_doc.flags.ignore_mandatory = True
si_doc.due_date = si_doc.posting_date
si_doc.insert()
return name_list
def save_invoice(e, si_doc, name, name_list):
try:
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
si_doc.docstatus = 0
si_doc.flags.ignore_mandatory = True
si_doc.due_date = si_doc.posting_date
si_doc.insert()
name_list.append(name)
except Exception:
frappe.log_error(frappe.get_traceback())
return name_list

View File

@@ -0,0 +1,43 @@
QUnit.module('Sales Invoice');
QUnit.test("test sales Invoice", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Sales Invoice', [
{customer: 'Test Customer 1'},
{items: [
[
{'qty': 5},
{'item_code': 'Test Product 1'},
]
]},
{update_stock:1},
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
},
() => cur_frm.save(),
() => {
// get_item_details
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
// get tax details
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
// get tax account head details
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
// grand_total Calculated
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,43 @@
QUnit.module('Sales Invoice');
QUnit.test("test sales Invoice", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Sales Invoice', [
{customer: 'Test Customer 1'},
{items: [
[
{'qty': 5},
{'item_code': 'Test Product 1'},
]
]},
{update_stock:1},
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
},
() => cur_frm.save(),
() => {
// get_item_details
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
// get tax details
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
// get tax account head details
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
// grand_total Calculated
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,56 @@
QUnit.module('Sales Invoice');
QUnit.test("test sales Invoice with payment", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Sales Invoice', [
{customer: 'Test Customer 1'},
{items: [
[
{'qty': 5},
{'item_code': 'Test Product 1'},
]
]},
{update_stock:1},
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
},
() => cur_frm.save(),
() => {
// get_item_details
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
// get tax details
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
// grand_total Calculated
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(2),
() => frappe.tests.click_button('Close'),
() => frappe.tests.click_button('Make'),
() => frappe.tests.click_link('Payment'),
() => frappe.timeout(0.2),
() => { cur_frm.set_value('mode_of_payment','Cash');},
() => { cur_frm.set_value('paid_to','Cash - '+frappe.get_abbr(frappe.defaults.get_default('Company')));},
() => {cur_frm.set_value('reference_no','TEST1234');},
() => {cur_frm.set_value('reference_date',frappe.datetime.add_days(frappe.datetime.nowdate(), 0));},
() => cur_frm.save(),
() => {
// get payment details
assert.ok(cur_frm.doc.paid_amount==590, "Paid Amount Correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => done()
]);
});

View File

@@ -426,11 +426,16 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
});
this.serach_item.make_input();
this.serach_item.$input.on("keyup", function () {
setTimeout(function () {
me.items = me.get_items();
me.make_item_list();
}, 1000);
this.serach_item.$input.on("keypress", function (event) {
clearTimeout(me.last_search_timeout);
me.last_search_timeout = setTimeout(() => {
if((me.serach_item.$input.val() != "") || (event.which == 13)) {
me.items = me.get_items();
me.make_item_list();
}
}, 400);
});
this.search_item_group = this.wrapper.find('.search-item-group');
@@ -727,14 +732,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
input = input.toLowerCase();
item = this.get_item(item.value);
var searchtext =
Object.keys(item)
.filter(key => ['customer_name', 'customer_group', 'value', 'label', 'email_id', 'phone', 'mobile_no'].includes(key))
.map(key => item[key])
.join(" ")
.toLowerCase();
return searchtext.includes(input)
return item.searchtext.includes(input)
},
item: function (item, input) {
var d = this.get_item(item.value);
@@ -808,7 +806,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
territory: c.territory,
phone: contact ? contact["phone"] : '',
mobile_no: contact ? contact["mobile_no"] : '',
email_id: contact ? contact["email_id"] : ''
email_id: contact ? contact["email_id"] : '',
searchtext: ['customer_name', 'customer_group', 'value',
'label', 'email_id', 'phone', 'mobile_no']
.map(key => c[key]).join(' ')
.toLowerCase()
}
});

View File

@@ -6,11 +6,11 @@ QUnit.test("test:POS Profile", function(assert) {
() => {
return frappe.tests.make("POS Profile", [
{naming_series: "SINV"},
{company: "_Test Company"},
{company: "Test Company"},
{country: "India"},
{currency: "INR"},
{write_off_account: "Write Off - _TC"},
{write_off_cost_center: "Main - _TC"},
{write_off_account: "Write Off - TC"},
{write_off_cost_center: "Main - TC"},
{payments: [
[
{"default": 1},
@@ -35,15 +35,16 @@ QUnit.test("test:Sales Invoice", function(assert) {
frappe.run_serially([
() => {
return frappe.tests.make("Sales Invoice", [
{customer: "_Test Customer 2"},
{company: "_Test Company"},
{customer: "Test Customer 2"},
{company: "Test Company"},
{is_pos: 1},
{posting_date: frappe.datetime.get_today()},
{due_date: frappe.datetime.get_today()},
{items: [
[
{"item_code": "_Test Item"},
{"qty": 5}
{"item_code": "Test Product 1"},
{"qty": 5},
{"warehouse":'Stores - TC'}
]]
}
]);

View File

@@ -7,7 +7,7 @@ frappe.query_reports["Item-wise Purchase Register"] = {
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{

View File

@@ -7,7 +7,7 @@ frappe.query_reports["Item-wise Sales Register"] = frappe.query_reports["Sales R
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_default("year_start_date"),
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{

View File

@@ -7,7 +7,7 @@ frappe.query_reports["Purchase Register"] = {
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{

View File

@@ -7,7 +7,7 @@ frappe.query_reports["Sales Register"] = {
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_default("year_start_date"),
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"width": "80"
},
{

View File

@@ -0,0 +1,65 @@
QUnit.module('Buying');
QUnit.test("test: purchase order", function(assert) {
assert.expect(11);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{currency: 'INR'},
{items: [
[
{"item_code": 'Test Product 4'},
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"qty": 5},
{"uom": 'Unit'},
{"rate": 100},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]},
{tc_name: 'Test Term 1'},
{terms: 'This is a term.'}
]);
},
() => {
// Get supplier details
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
assert.ok($('div.control-value.like-disabled-input.for-description').text().includes('Contact 3'), "Contact display correct");
assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Contact email correct");
// Get item details
assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
assert.ok(cur_frm.doc.items[0].description == 'Test Product 4', "Description correct");
assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
// Calculate total
assert.ok(cur_frm.doc.total == 500, "Total correct");
// Get terms
assert.ok(cur_frm.doc.terms == 'This is a term.', "Terms correct");
},
() => cur_frm.print_doc(),
() => frappe.timeout(2),
() => {
assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
assert.ok($('div > div:nth-child(5) > div > div > table > tbody > tr > td:nth-child(4) > div').text().includes('Test Product 4'), "Print Preview Works");
},
() => cur_frm.print_doc(),
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => {
assert.ok(cur_frm.doc.status == 'To Receive and Bill', "Submitted successfully");
},
() => done()
]);
});

View File

@@ -0,0 +1,61 @@
QUnit.module('Buying');
QUnit.test("test: purchase order with get items", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{buying_price_list: 'Test-Buying-USD'},
{currency: 'USD'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]}
]);
},
() => {
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
},
() => frappe.timeout(0.3),
() => frappe.click_button('Get items from'),
() => frappe.timeout(0.3),
() => frappe.click_link('Product Bundle'),
() => frappe.timeout(0.5),
() => cur_dialog.set_value('product_bundle', 'Computer'),
() => frappe.click_button('Get Items'),
() => frappe.timeout(1),
// Check if items are fetched from Product Bundle
() => {
assert.ok(cur_frm.doc.items[1].item_name == 'CPU', "Product bundle item 1 correct");
assert.ok(cur_frm.doc.items[2].item_name == 'Screen', "Product bundle item 2 correct");
assert.ok(cur_frm.doc.items[3].item_name == 'Keyboard', "Product bundle item 3 correct");
},
() => cur_frm.doc.items[1].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
() => cur_frm.doc.items[2].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
() => cur_frm.doc.items[3].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
() => cur_frm.save(),
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,74 @@
QUnit.module('Buying');
QUnit.test("test: purchase order receipt", function(assert) {
assert.expect(5);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{buying_price_list: 'Test-Buying-USD'},
{currency: 'USD'},
{items: [
[
{"item_code": 'Test Product 1'},
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"qty": 5},
{"uom": 'Unit'},
{"rate": 100},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]},
]);
},
() => {
// Check supplier and item details
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 1', "Item name correct");
assert.ok(cur_frm.doc.items[0].description == 'Test Product 1', "Description correct");
assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
},
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(1.5),
() => frappe.click_button('Close'),
() => frappe.timeout(0.3),
// Make Purchase Receipt
() => frappe.click_button('Make'),
() => frappe.timeout(0.3),
() => frappe.click_link('Receipt'),
() => frappe.timeout(2),
() => cur_frm.save(),
// Save and submit Purchase Receipt
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(1),
// View Purchase order in Stock Ledger
() => frappe.click_button('View'),
() => frappe.timeout(0.3),
() => frappe.click_link('Stock Ledger'),
() => frappe.timeout(2),
() => {
assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1')
&& $('div.slick-cell.l9.r9 > div').text().includes(5), "Stock ledger entry correct");
},
() => done()
]);
});

View File

@@ -0,0 +1,47 @@
QUnit.module('Buying');
QUnit.test("test: purchase order with discount on grand total", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{buying_price_list: 'Test-Buying-EUR'},
{currency: 'EUR'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"uom": 'Unit'},
{"rate": 500 },
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]},
{apply_discount_on: 'Grand Total'},
{additional_discount_percentage: 10}
]);
},
() => frappe.timeout(1),
() => {
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
assert.ok(cur_frm.doc.items[0].rate == 500, "Rate correct");
// Calculate total
assert.ok(cur_frm.doc.total == 2500, "Total correct");
// Calculate grand total after discount
assert.ok(cur_frm.doc.grand_total == 2250, "Grand total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,44 @@
QUnit.module('Buying');
QUnit.test("test: purchase order with item wise discount", function(assert) {
assert.expect(4);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{buying_price_list: 'Test-Buying-EUR'},
{currency: 'EUR'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"uom": 'Unit'},
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
{"discount_percentage": 20}
]
]}
]);
},
() => frappe.timeout(1),
() => {
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
assert.ok(cur_frm.doc.items[0].discount_percentage == 20, "Discount correct");
// Calculate totals after discount
assert.ok(cur_frm.doc.total == 2000, "Total correct");
assert.ok(cur_frm.doc.grand_total == 2000, "Grand total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,39 @@
QUnit.module('Buying');
QUnit.test("test: purchase order with multi UOM", function(assert) {
assert.expect(3);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"uom": 'Unit'},
{"rate": 100},
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]}
]);
},
() => {
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi UOM correct");
},
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,43 @@
QUnit.module('Buying');
QUnit.test("test: purchase order with taxes and charges", function(assert) {
assert.expect(3);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Purchase Order', [
{supplier: 'Test Supplier'},
{is_subcontracted: 'No'},
{buying_price_list: 'Test-Buying-USD'},
{currency: 'USD'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"uom": 'Unit'},
{"rate": 500 },
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
{"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]},
{taxes_and_charges: 'TEST In State GST'}
]);
},
() => {
// Check taxes and calculate grand total
assert.ok(cur_frm.doc.taxes[1].account_head=='SGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), "Account Head abbr correct");
assert.ok(cur_frm.doc.total_taxes_and_charges == 225, "Taxes and charges correct");
assert.ok(cur_frm.doc.grand_total == 2725, "Grand total correct");
},
() => frappe.timeout(0.3),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -138,7 +138,6 @@ frappe.ui.form.on("Request for Quotation",{
dialog.show();
},
make_suppplier_quotation: function(frm) {
var doc = frm.doc;
var dialog = new frappe.ui.Dialog({
@@ -207,6 +206,29 @@ frappe.ui.form.on("Request for Quotation Supplier",{
if(!w) {
frappe.msgprint(__("Please enable pop-ups")); return;
}
},
no_quote: function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.no_quote) {
if (d.quote_status != __('Received')) {
frappe.model.set_value(cdt, cdn, 'quote_status', 'No Quote');
} else {
frappe.msgprint(__("Cannot set a received RFQ to No Quote"));
frappe.model.set_value(cdt, cdn, 'no_quote', 0);
}
} else {
d.quote_status = __('Pending');
frm.call({
method:"update_rfq_supplier_status",
doc: frm.doc,
args: {
sup_name: d.supplier
},
callback: function(r) {
frm.refresh_field("suppliers");
}
});
}
}
})

View File

@@ -54,6 +54,7 @@ class RequestforQuotation(BuyingController):
frappe.db.set(self, 'status', 'Submitted')
for supplier in self.suppliers:
supplier.email_sent = 0
supplier.quote_status = 'Pending'
def on_cancel(self):
frappe.db.set(self, 'status', 'Cancelled')
@@ -157,6 +158,28 @@ class RequestforQuotation(BuyingController):
attachments.append(frappe.attach_print(self.doctype, self.name, doc=self))
return attachments
def update_rfq_supplier_status(self, sup_name=None):
for supplier in self.suppliers:
if sup_name == None or supplier.supplier == sup_name:
if supplier.quote_status != _('No Quote'):
quote_status = _('Received')
for item in self.items:
sqi_count = frappe.db.sql("""
SELECT
COUNT(sqi.name) as count
FROM
`tabSupplier Quotation Item` as sqi,
`tabSupplier Quotation` as sq
WHERE sq.supplier = %(supplier)s
AND sqi.docstatus = 1
AND sqi.request_for_quotation_item = %(rqi)s
AND sqi.parent = sq.name""",
{"supplier": supplier.supplier, "rqi": item.name}, as_dict=1)[0]
if (sqi_count.count) == 0:
quote_status = _('Pending')
supplier.quote_status = quote_status
@frappe.whitelist()
def send_supplier_emails(rfq_name):
check_portal_enabled('Request for Quotation')
@@ -172,7 +195,12 @@ def check_portal_enabled(reference_doctype):
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
list_context = get_list_context(context)
list_context["show_sidebar"] = True
list_context.update({
'show_sidebar': True,
'show_search': True,
'no_breadcrumbs': True,
'title': _('Request for Quotation'),
})
return list_context
def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):

View File

@@ -10,21 +10,41 @@ from erpnext.templates.pages.rfq import check_supplier_has_docname_access
from frappe.utils import nowdate
class TestRequestforQuotation(unittest.TestCase):
def test_quote_status(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
rfq = make_request_for_quotation()
self.assertEquals(rfq.get('suppliers')[0].quote_status, 'Pending')
self.assertEquals(rfq.get('suppliers')[1].quote_status, 'Pending')
# Submit the first supplier quotation
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
sq.submit()
# No Quote first supplier quotation
rfq.get('suppliers')[1].no_quote = 1
rfq.get('suppliers')[1].quote_status = 'No Quote'
rfq.update_rfq_supplier_status() #rfq.get('suppliers')[1].supplier)
self.assertEquals(rfq.get('suppliers')[0].quote_status, 'Received')
self.assertEquals(rfq.get('suppliers')[1].quote_status, 'No Quote')
def test_make_supplier_quotation(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
rfq = make_request_for_quotation()
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
sq.submit()
sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier)
sq1.submit()
self.assertEquals(sq.supplier, rfq.get('suppliers')[0].supplier)
self.assertEquals(sq.get('items')[0].request_for_quotation, rfq.name)
self.assertEquals(sq.get('items')[0].item_code, "_Test Item")
self.assertEquals(sq.get('items')[0].qty, 5)
self.assertEquals(sq1.supplier, rfq.get('suppliers')[1].supplier)
self.assertEquals(sq1.get('items')[0].request_for_quotation, rfq.name)
self.assertEquals(sq1.get('items')[0].item_code, "_Test Item")
@@ -61,15 +81,15 @@ class TestRequestforQuotation(unittest.TestCase):
rfq.get('items')[0].rate = 100
rfq.supplier = rfq.suppliers[0].supplier
supplier_quotation_name = create_supplier_quotation(rfq)
supplier_quotation_doc = frappe.get_doc('Supplier Quotation', supplier_quotation_name)
self.assertEquals(supplier_quotation_doc.supplier, rfq.get('suppliers')[0].supplier)
self.assertEquals(supplier_quotation_doc.get('items')[0].request_for_quotation, rfq.name)
self.assertEquals(supplier_quotation_doc.get('items')[0].item_code, "_Test Item")
self.assertEquals(supplier_quotation_doc.get('items')[0].qty, 5)
self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500)
def make_request_for_quotation(supplier_data=None):
"""
@@ -81,10 +101,10 @@ def make_request_for_quotation(supplier_data=None):
rfq.status = 'Draft'
rfq.company = '_Test Company'
rfq.message_for_supplier = 'Please supply the specified items at the best possible rates.'
for data in supplier_data:
rfq.append('suppliers', data)
rfq.append("items", {
"item_code": "_Test Item",
"description": "_Test Item",
@@ -93,11 +113,11 @@ def make_request_for_quotation(supplier_data=None):
"warehouse": "_Test Warehouse - _TC",
"schedule_date": nowdate()
})
rfq.submit()
return rfq
def get_supplier_data():
return [{
"supplier": "_Test Supplier",

View File

@@ -0,0 +1,75 @@
QUnit.module('Buying');
QUnit.test("test: request_for_quotation", function(assert) {
assert.expect(14);
let done = assert.async();
let date;
frappe.run_serially([
() => {
date = frappe.datetime.add_days(frappe.datetime.now_date(), 10);
return frappe.tests.make('Request for Quotation', [
{transaction_date: date},
{suppliers: [
[
{"supplier": 'Test Supplier'},
{"email_id": 'test@supplier.com'}
]
]},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)},
{"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]},
{message_for_supplier: 'Please supply the specified items at the best possible rates'},
{tc_name: 'Test Term 1'}
]);
},
() => {
assert.ok(cur_frm.doc.transaction_date == date, "Date correct");
assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct");
assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct");
assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct");
assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct");
assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct");
assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company")), "Warehouse correct");
assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct");
assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct");
},
() => frappe.timeout(0.3),
() => cur_frm.print_doc(),
() => frappe.timeout(1),
() => {
assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
assert.ok($('.section-break+ .section-break .column-break:nth-child(1) .value').text().includes("Test Product 4"), "Print Preview Works");
},
() => cur_frm.print_doc(),
() => frappe.timeout(1),
() => frappe.click_button('Get items from'),
() => frappe.timeout(0.3),
() => frappe.click_link('Material Request'),
() => frappe.timeout(1),
() => frappe.click_button('Get Items'),
() => frappe.timeout(1),
() => {
assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work");
},
() => cur_frm.save(),
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(1),
() => {
assert.ok(cur_frm.doc.docstatus == 1, "Quotation request submitted");
},
() => frappe.click_button('Send Supplier Emails'),
() => frappe.timeout(3),
() => {
assert.ok($('div.modal.fade.in > div.modal-dialog > div > div.modal-body.ui-front > div.msgprint').text().includes("Email sent to supplier Test Supplier"), "Send emails working");
},
() => frappe.click_button('Close'),
() => done()
]);
});

View File

@@ -0,0 +1,132 @@
QUnit.module('buying');
QUnit.test("Test: Request for Quotation", function (assert) {
assert.expect(5);
let done = assert.async();
let rfq_name = "";
frappe.run_serially([
// Go to RFQ list
() => frappe.set_route("List", "Request for Quotation"),
// Create a new RFQ
() => frappe.new_doc("Request for Quotation"),
() => frappe.timeout(1),
() => cur_frm.set_value("transaction_date", "04-04-2017"),
() => cur_frm.set_value("company", "_Test Company"),
// Add Suppliers
() => {
cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view();
},
() => frappe.timeout(1),
() => {
cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier";
frappe.click_check('Send Email');
cur_frm.cur_grid.frm.script_manager.trigger('supplier');
},
() => frappe.timeout(1),
() => {
cur_frm.cur_grid.toggle_view();
},
() => frappe.timeout(1),
() => frappe.click_button('Add Row',0),
() => frappe.timeout(1),
() => {
cur_frm.fields_dict.suppliers.grid.grid_rows[1].toggle_view();
},
() => frappe.timeout(1),
() => {
cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1";
frappe.click_check('Send Email');
cur_frm.cur_grid.frm.script_manager.trigger('supplier');
},
() => frappe.timeout(1),
() => {
cur_frm.cur_grid.toggle_view();
},
() => frappe.timeout(1),
// Add Item
() => {
cur_frm.fields_dict.items.grid.grid_rows[0].toggle_view();
},
() => frappe.timeout(1),
() => {
cur_frm.fields_dict.items.grid.grid_rows[0].doc.item_code = "_Test Item";
frappe.set_control('item_code',"_Test Item");
frappe.set_control('qty',5);
frappe.set_control('schedule_date', "05-05-2017");
cur_frm.cur_grid.frm.script_manager.trigger('supplier');
},
() => frappe.timeout(2),
() => {
cur_frm.cur_grid.toggle_view();
},
() => frappe.timeout(2),
() => {
cur_frm.fields_dict.items.grid.grid_rows[0].doc.warehouse = "_Test Warehouse - _TC";
},
() => frappe.click_button('Save'),
() => frappe.timeout(1),
() => frappe.click_button('Submit'),
() => frappe.timeout(1),
() => frappe.click_button('Yes'),
() => frappe.timeout(1),
() => frappe.click_button('Menu'),
() => frappe.timeout(1),
() => frappe.click_link('Reload'),
() => frappe.timeout(1),
() => {
assert.equal(cur_frm.doc.docstatus, 1);
rfq_name = cur_frm.doc.name;
assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.quote_status == "Pending");
assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Pending");
},
() => {
cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view();
},
() => frappe.timeout(1),
() => {
frappe.click_check('No Quote');
},
() => frappe.timeout(1),
() => {
cur_frm.cur_grid.toggle_view();
},
() => frappe.click_button('Update'),
() => frappe.timeout(1),
() => frappe.click_button('Supplier Quotation'),
() => frappe.timeout(1),
() => frappe.click_link('Make'),
() => frappe.timeout(1),
() => {
frappe.set_control('supplier',"_Test Supplier 1");
},
() => frappe.timeout(1),
() => frappe.click_button('Make Supplier Quotation'),
() => frappe.timeout(1),
() => cur_frm.set_value("company", "_Test Company"),
() => cur_frm.fields_dict.items.grid.grid_rows[0].doc.rate = 4.99,
() => frappe.timeout(1),
() => frappe.click_button('Save'),
() => frappe.timeout(1),
() => frappe.click_button('Submit'),
() => frappe.timeout(1),
() => frappe.click_button('Yes'),
() => frappe.timeout(1),
() => frappe.set_route("List", "Request for Quotation"),
() => frappe.timeout(2),
() => frappe.set_route("List", "Request for Quotation"),
() => frappe.timeout(2),
() => frappe.click_link(rfq_name),
() => frappe.timeout(1),
() => frappe.click_button('Menu'),
() => frappe.timeout(1),
() => frappe.click_link('Reload'),
() => frappe.timeout(1),
() => {
assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Received");
assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.no_quote == 1);
},
() => done()
]);
});

View File

@@ -137,6 +137,69 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus >= 1 && doc.quote_status != 'Received'",
"fieldname": "no_quote",
"fieldtype": "Check",
"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": "No Quote",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus >= 1 && !doc.no_quote",
"fieldname": "quote_status",
"fieldtype": "Select",
"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": "Quote Status",
"length": 0,
"no_copy": 0,
"options": "Pending\nReceived\nNo Quote",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -269,7 +332,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-07-24 06:52:19.542717",
"modified": "2017-07-26 22:25:58.096584",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation Supplier",

View File

@@ -8,9 +8,8 @@ QUnit.test("test: supplier", function(assert) {
return frappe.tests.make('Supplier', [
{supplier_name: 'Test Supplier'},
{supplier_type: 'Hardware'},
{country: 'United States'},
{default_currency: 'USD'},
{default_price_list: 'Test-Buying-USD'},
{country: 'India'},
{default_currency: 'INR'},
{credit_days_based_on: 'Fixed Days'},
{accounts: [
[
@@ -68,7 +67,7 @@ QUnit.test("test: supplier", function(assert) {
() => {
assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Name correct");
assert.ok(cur_frm.doc.supplier_type == 'Hardware', "Type correct");
assert.ok(cur_frm.doc.default_currency == 'USD', "Currency correct");
assert.ok(cur_frm.doc.default_currency == 'INR', "Currency correct");
assert.ok(cur_frm.doc.accounts[0].account == 'Creditors - '+frappe.get_abbr('Test Company'), " Account Head abbr correct");
assert.ok($('.address-box:nth-child(3) p').text().includes('Shipping City 3'), "Address correct");
assert.ok($('.col-sm-6+ .col-sm-6 .h6').text().includes('Contact 3'), "Contact correct");

View File

@@ -31,9 +31,11 @@ class SupplierQuotation(BuyingController):
def on_submit(self):
frappe.db.set(self, "status", "Submitted")
self.update_rfq_supplier_status(1)
def on_cancel(self):
frappe.db.set(self, "status", "Cancelled")
self.update_rfq_supplier_status(0)
def on_trash(self):
pass
@@ -50,6 +52,41 @@ class SupplierQuotation(BuyingController):
"is_child_table": True
}
})
def update_rfq_supplier_status(self, include_me):
rfq_list = set([])
for item in self.items:
if item.request_for_quotation:
rfq_list.add(item.request_for_quotation)
for rfq in rfq_list:
doc = frappe.get_doc('Request for Quotation', rfq)
doc_sup = frappe.get_all('Request for Quotation Supplier', filters=
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0]
quote_status = _('Received')
for item in doc.items:
sqi_count = frappe.db.sql("""
SELECT
COUNT(sqi.name) as count
FROM
`tabSupplier Quotation Item` as sqi,
`tabSupplier Quotation` as sq
WHERE sq.supplier = %(supplier)s
AND sqi.docstatus = 1
AND sq.name != %(me)s
AND sqi.request_for_quotation_item = %(rqi)s
AND sqi.parent = sq.name""",
{"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0]
self_count = sum(my_item.request_for_quotation_item == item.name
for my_item in self.items) if include_me else 0
if (sqi_count.count + self_count) == 0:
quote_status = _('Pending')
if quote_status == _('Received') and doc_sup.quote_status == _('No Quote'):
frappe.msgprint(_("{0} indicates that {1} will not provide a quotation, but all items \
have been quoted. Updating the RFQ quote status.").format(doc.name, self.supplier))
frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status)
frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'no_quote', 0)
elif doc_sup.quote_status != _('No Quote'):
frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status)
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context

View File

@@ -0,0 +1,73 @@
QUnit.module('Buying');
QUnit.test("test: supplier quotation", function(assert) {
assert.expect(11);
let done = assert.async();
let date;
frappe.run_serially([
() => {
date = frappe.datetime.add_days(frappe.datetime.now_date(), 10);
return frappe.tests.make('Supplier Quotation', [
{supplier: 'Test Supplier'},
{transaction_date: date},
{currency: 'INR'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"uom": 'Unit'},
{"rate": 200},
{"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
]
]},
{apply_discount_on: 'Grand Total'},
{additional_discount_percentage: 10},
{tc_name: 'Test Term 1'},
{terms: 'This is a term'}
]);
},
() => {
// Get Supplier details
assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct");
assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct");
// Get Contact details
assert.ok(cur_frm.doc.contact_display == 'Contact 3', "Conatct correct");
assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct");
// Get uom
assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi uom correct");
assert.ok(cur_frm.doc.total == 1000, "Total correct");
// Calculate total after discount
assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct");
// Get terms
assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Terms correct");
},
() => cur_frm.print_doc(),
() => frappe.timeout(2),
() => {
assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
assert.ok($("table > tbody > tr > td:nth-child(3) > div").text().includes("Test Product 4"), "Print Preview Works As Expected");
},
() => cur_frm.print_doc(),
() => frappe.timeout(1),
() => frappe.click_button('Get items from'),
() => frappe.timeout(0.3),
() => frappe.click_link('Material Request'),
() => frappe.timeout(0.3),
() => frappe.click_button('Get Items'),
() => frappe.timeout(1),
() => {
// Get item from Material Requests
assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work");
},
() => cur_frm.save(),
() => frappe.timeout(1),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,34 @@
QUnit.module('Buying');
QUnit.test("test: supplier quotation with item wise discount", function(assert){
assert.expect(2);
let done = assert.async();
frappe.run_serially([
() => {
return frappe.tests.make('Supplier Quotation', [
{supplier: 'Test Supplier'},
{company: 'Test Company'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"uom": 'Unit'},
{"warehouse": 'All Warehouses - TC'},
{'discount_percentage': 10},
]
]}
]);
},
() => {
assert.ok(cur_frm.doc.total == 900, "Total correct");
assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct");
},
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -0,0 +1,37 @@
QUnit.module('Buying');
QUnit.test("test: supplier quotation with taxes and charges", function(assert) {
assert.expect(3);
let done = assert.async();
let supplier_quotation_name;
frappe.run_serially([
() => {
return frappe.tests.make('Supplier Quotation', [
{supplier: 'Test Supplier'},
{items: [
[
{"item_code": 'Test Product 4'},
{"qty": 5},
{"rate": 100},
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
]
]},
{taxes_and_charges:'TEST In State GST'},
]);
},
() => {supplier_quotation_name = cur_frm.doc.name;},
() => {
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
assert.ok(cur_frm.doc.total_taxes_and_charges == 45, "Taxes and charges correct");
assert.ok(cur_frm.doc.grand_total == 545, "Grand total correct");
},
() => cur_frm.save(),
() => frappe.timeout(0.3),
() => frappe.tests.click_button('Submit'),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(0.3),
() => done()
]);
});

View File

@@ -70,8 +70,8 @@ def get_data():
"items": [
{
"type": "doctype",
"name": "BOM Replace Tool",
"description": _("Replace Item / BOM in all BOMs"),
"name": "BOM Update Tool",
"description": _("Replace BOM and update latest price in all BOMs"),
},
]
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

View File

@@ -23,6 +23,15 @@ You can change accounting currency in Party / Account record, until making any t
In case of multi-company setup, accounting currency of Party must be same for all the companies.
### Exchange Rates
When dealing with multiple currencies, ERPNext has the Currency Exchange module for managing exchange rates. It allows you to save the exchange rate quotes you require.
For foreign currency transactions, ERPNext checks Currency Exchange for any matching record. If this fails, ERPNext will attempt to get the exchange rate quote from [fixer.io](http://fixer.io). If this still fails, then the exchange rate will have to be entered manually.
#### Exchange Rate Selection
ERPNext automatically fetches the latest exchange rate available.
## Transactions
### Sales Invoice
@@ -50,61 +59,6 @@ In Accounts table, on selection of foreign currency account, system will show Cu
<img class="screenshot" alt="Journal Entry in multi currency" src="/docs/assets/img/accounts/multi-currency/journal-entry-row.png">
#### Example 1: Payment Entry Against Customer With Alternate Currency
Suppose, default currency of the company is INR and customer's accounting currency is USD. Customer made full payment against an outstanding invoice of USD 100. Exchange Rate (USD -> INR) in Sales Invoice was 60.
Exchange Rate in the payment entry should always be same as invoice (60), even if exchange rate on the payment date is 62. The bank account will be credited by the amount considering exchange rate as 62. Hence, Exchnage Gain / Loss will be booked based on exchange rate difference.
<img class="screenshot" alt="Payment Entry" src="/docs/assets/img/accounts/multi-currency/payment-entry.png">
#### Example 2: Inter-bank Transfer (USD -> INR)
Suppose the default currency of the company is INR. You have a Paypal account for which Currency is USD. You receive payments in the paypal account and lets say, paypal transfers amount once in a week to your other bank account which is managed in INR.
Paypal account gets debited on different date with different exchange rate, but on transfer date the exchange rate can be different. Hence, there is generally Exchange Loss / Gain on the transfer entry.
In the bank transfer entry, system sets exchange rate of the credit account (Paypal) based on the average incoming exchange rate. This is to maintain Paypal balance properly in company currency. In case you modify the average exchange rate, you need to adjust the exchange rate manually in the future entries, so that balance in account currency and company currency are in sync.
Then you should calculate and enter Exchange Loss / Gain based on the Paypal exchange rate and the exchange rate on the transfer date.
Lets say, Paypal account debited by following amounts over the week, which has not been transferred to your other bank account.
<table class="table table-bordered">
<thead>
<tr>
<td>Date</td>
<td>Account</td>
<td>Debit (USD)</td>
<td>Exchange Rate</td>
</tr>
</thead>
<tbody>
<tr>
<td>2015-09-02</td>
<td>Paypal</td>
<td>100</td>
<td>60</td>
</tr>
<tr>
<td>2015-09-02</td>
<td>Paypal</td>
<td>100</td>
<td>61</td>
</tr>
<tr>
<td>2015-09-02</td>
<td>Paypal</td>
<td>100</td>
<td>64</td>
</tr>
</tbody>
</table>
Suppose, Exchange Rate on the payment date is 62 and Bank Transfer Entry will be look like below:
<img class="screenshot" alt="Inter Bank Transfer" src="/docs/assets/img/accounts/multi-currency/bank-transfer.png">
## Reports
### General Ledger

View File

@@ -2,43 +2,40 @@
A Request for Quotation is a document that an organization submits to one or more suppliers eliciting quotation for items.
In ERPNext, You can create request for quotation directly by going to:
In ERPNext, You can create Request for Quotation directly by going to:
> Buying > Documents > Request for Quotation > New Request for Quotation
![Request For Quotation](/docs/assets/img/buying/request-for-quotation.png)
After creation of Request for Quotation, there are two ways to generate Supplier Quotation from Request for Quotation.
After creation of request for quotation, there are two ways to generate supplier quotation from request for quotation.
#### For User
__Step 1:__ Open request for quotation and click on make supplier quotation.
__Step 1:__ Open Request for Quotation and click on make Supplier Quotation.
![Request For Quotation](/docs/assets/img/buying/make-supplier-quotation-from-rfq.png)
__Step 2:__ Select supplier and click on make supplier quotation.
__Step 2:__ Select supplier and click on make Supplier Quotation.
![Request For Quotation](/docs/assets/img/buying/supplier-selection-from-rfq.png)
__Step 3:__ System will open the supplier quotation, user has to enter the rate and submit it.
__Step 3:__ System will open the Supplier Quotation, user has to enter the rate and submit it.
![Request For Quotation](/docs/assets/img/buying/supplier-quotation-from-rfq.png)
#### For Supplier
__Step 1:__ User has to create contact or enter Email Address against the supplier on request for quotation.
__Step 1:__ User has to create contact or enter Email Address against the supplier on Request for Quotation.
![Request For Quotation](/docs/assets/img/buying/set-email-id.png)
__Step 2:__ User has to click on send supplier emails button.
![Request For Quotation](/docs/assets/img/buying/send-supplier-emails.png)
* If supplier's user not available: system will create supplier's user and send details to the supplier, supplier will need to click on the link(Password Update) present in the email. After password update supplier can access his portal with the request for quotation form.
* If supplier's user not available: system will create supplier's user and send details to the supplier, supplier will need to click on the link(Password Update) present in the email. After password update supplier can access his portal with the Request for Quotation form.
![Request For Quotation](/docs/assets/img/buying/supplier-password-update-link.png)
* If supplier's user available: system will send request for quotation link to supplier, supplier has to login using his credentials to view request for quotation form on portal.
* If supplier's user available: system will send Request for Quotation link to supplier, supplier has to login using his credentials to view Request for Quotation form on portal.
![Request For Quotation](/docs/assets/img/buying/send-rfq-link.png)
@@ -46,9 +43,12 @@ __Step 3:__ Supplier has to enter amount and notes(payment terms) on the form an
![Request For Quotation](/docs/assets/img/buying/supplier-portal-rfq.png)
__Step 4:__ On submission, system will create supplier quotation(draft mode) against the supplier. User has to review the supplier quotation
and submit it.
More details:-
__Step 4:__ On submission, system will create Supplier Quotation (draft mode) against the supplier. The user has to review the Supplier Quotation
and submit it. When all items from the Request for Quotation have been quoted by a supplier, the status is updated in the Supplier
table of the Request for Quotation.
![Request For Quotation](/docs/assets/img/buying/request-for-quotation.gif)
#### More details
If a supplier indicates that they will not provide a quotation for the item, this can be indicated in the RFQ document by checking the 'No Quote' box after the Request for Quotation has been submitted.
![Request For Quotation](/docs/assets/img/buying/request-for-quotation.gif)

View File

@@ -1,44 +0,0 @@
# BOM Replace Tool
Replace BOM is the utility to replace BOM of sub-assembly item, which is already updated in the BOM of Finished Good item.
To use the Production Planning Tool, go to:
> Manufacturing > Tools > BOM Replace Tool
Let's consider a scenario to understand this better.
If company manufactures computers, Bill of Material of its finished item will constitute of:
1. Monitor
1. Key Board
1. Mouse
1. CPU
Out of all the items above, CPU is asembled separately. Hence separate BOM will be created for the CPU. Following are the items from the BOM of CPU.
1. 250 GB Hard Disk
1. Mother Board
1. Processor
1. SMTP
1. DVD player
If we have more items to be added , or existing items to be edited in the BOM of CPU, then we should create new BOM for it.
1. _350 GB Hard Disk_
1. Mother Board
1. Processor
1. SMTP
1. DVD player
To update new BOM updated in the BOM of finished item, where CPU is selected as raw-material, you can use BOM Replace tool.
<img class="screenshot" alt="BOM replace Tool" src="/docs/assets/img/manufacturing/bom-replace-tool.png">
In this tool, you should select Current BOM, and New BOM. On clicking Replace button, current BOM of CPU will be replaced with New BOM in the BOM of finished Item (Computer).
**Will BOM Replace Tool work for replacing finsihed item in BOM?**
No. You should Cancel and Amend current BOM, or create a new BOM for finished item.
{next}

View File

@@ -0,0 +1,54 @@
# BOM Update Tool
From BOM Update Tool, you can replace a sub-assembly BOM and update costs of all BOMs.
### Replace BOM
Using this utility, you can replace an existing BOM of sub-assembly item, with a new one. The system will update the new BOM in all the parent BOMs where it was used.
To use the BOM Update Tool, go to:
> Manufacturing > Tools > BOM Update Tool
Let's consider a scenario to understand this better.
Suppose a company manufactures computers, Bill of Material of of the computer will look like this:
1. Monitor
1. Key Board
1. Mouse
1. CPU
Out of all the items above, CPU is asembled separately. Hence separate BOM will be created for the CPU. Following are the items from the BOM of CPU.
1. 250 GB Hard Disk
1. Mother Board
1. Processor
1. SMTP
1. DVD player
If we have more items to be added , or existing items to be edited in the BOM of CPU, then we should create new BOM for it.
1. _350 GB Hard Disk_
1. Mother Board
1. Processor
1. SMTP
1. DVD player
To update new BOM in all the parent BOMs, where CPU is selected as raw-material, you can use Replace utility.
<img class="screenshot" alt="BOM Update Tool" src="{{docs_base_url}}/assets/img/manufacturing/bom-update-tool.png">
In this tool, you should select Current BOM, and New BOM. On clicking Replace button, current BOM of CPU will be replaced with New BOM in the BOM of finished Item (Computer).
**Will BOM Replace Tool work for replacing finsihed item in BOM?**
No. You should Cancel and Amend current BOM, or create a new BOM for finished item.
### Update BOM Cost
Using the button **Update latest price in all BOMs**, you can update cost of all Bill of Materials, based on latest purchase price / price list rate / valuation rate of raw materials.
On clicking of this buttom, system will create a background process to update all the BOM's cost. It is processed via background jobs because this process can take a few minutes (depending on the number of BOMs) to update all the BOMs.
This functionality can also be executed automatically on daily basis. For that, you need to enable "Update BOM Cost Automatically" from Manufacturing Settings.
{next}

View File

@@ -1,2 +1,2 @@
production-planning-tool
bom-replace-tool
bom-update-tool

View File

@@ -1,5 +1,6 @@
print-settings
print-format-builder
print-style
print-headings
letter-head
address-template

View File

@@ -0,0 +1,15 @@
# Print Style
Frappe/ERPNext comes with pre-set styles for your printed documents. You can also create new styles using CSS that can be applied to all your print formats.
To create a new **Print Style** go to **Setup > Printing and Branding > Print Style**, or just type "print style" in the search bar.
Here you can define the CSS rules for your print formats. These apply to both standard and custom print formats. To find out the various classes available, you can make a standard print format, open in a new page and see the source.
To set a default style, you can go to [Print Settings](/docs/setup/print/print-settings)
All Print Format styles are based on Bootstrap (Version 3) CSS Framework.
<img class="screenshot" alt="Print Style" src="/docs/assets/img/setup/print/print-style.png">
{next}

View File

@@ -1,2 +1,3 @@
introduction
accounts
schools

View File

@@ -0,0 +1,13 @@
#Criterios de Evaluación
Criterios de evaluación es el parámetro basado en el que se evalúa el estudiante.
<img class="screenshot" alt="Assessment Criteria" src="/docs/assets/img/schools/assessment/assessment-criteria.png">
Después de la evaluación para un curso, las calificaciones obtenidas se ingresan en base a los criterios de evaluación. Por ejemplo, si la evaluación se llevó a cabo para el tema de la ciencia, entonces usted puede evaluar al estudiante en ciencia en varios criterios como la escritura, prácticas, presentación, etc
Los Criterios de Evaluación se usan al programar el Plan de Evaluación para el Grupo de Estudiantes y el Curso.
<img class="screenshot" alt="Assessment Plan Criteria" src="/docs/assets/img/schools/assessment/assessment-plan-criteria.png">
{next}

View File

@@ -0,0 +1,13 @@
#Grupo de Evaluación
La estructura del grupo de evaluación es un maestro donde se puede definir la jerarquía para el examen realizado en su instituto de educación.
Por ejemplo, si realiza dos evaluaciones en un año académico, configure el Grupo de evaluación de la siguiente manera.
<img class="screenshot" alt="Assessment Group Term" src="/docs/assets/img/schools/assessment/assessment-group-term.png">
En la misma línea, también puede definir varios Grupo de Evaluación basado sobre la evaluación llevada a cabo en su instituto.
<img class="screenshot" alt="Assessment Group Term" src="/docs/assets/img/schools/assessment/assessment-group-details.png">
{next}

View File

@@ -0,0 +1,19 @@
#Plan de Evaluación
Para programar una evaluación/examinación para un Grupo de Estudiantes, para un curso específico, crea un Plan de Evaluación. En el plan de evaluación, puedes capturar detalles como:
1. Escala de Calificaciones basada en qué calificaciones serán asignadas a los estudiantes.
2. Fecha de planificación de la Evaluación
3. Aula donde se va a llevar a cabo la evaluación
4. Examinador y Supervisor
<img class="screenshot" alt="Assessment Plan Details" src="/docs/assets/img/schools/assessment/assessment-plan-details.png">
5. Los Criterios de Evaluación son la lista de criterios basados en que cada estudiante en será evaluado y los grados serán asignados.
<img class="screenshot" alt="Assessment Plan Criteria" src="/docs/assets/img/schools/assessment/assessment-plan-criteria.png">
{next}

View File

@@ -0,0 +1,7 @@
#Resultados de Evaluación
El resultado de la evaluación es un registro de las calificaciones obtenidas por el estudiante para una evaluación específica. El resultado de la evaluación se crea en el backend en base a los puntos en [Herramienta de Resultados de Evaluación](/docs/user/manual/es/schools/assessment/assessment_result_tool.html).
<img class="screenshot" alt="Assessment Result" src="/docs/assets/img/schools/assessment/assessment-result.png">
{next}

View File

@@ -0,0 +1,10 @@
#Herramienta de resultados de la evaluación
Herramienta de resultados de evaluación le ayuda a ingresar las calificaciones obtenidas por los estudiantes para un curso específico. En esta herramienta, basada en el plan de evaluación, todos los estudiantes van a ser filtrados dentro de la herramienta de resultados de la evaluación. También, Columnas para los Criterios de Evaluación serán donde las calificaciones ganadas pueden ser ingresadas para cada Estudiante.
<img class="screenshot" alt="Assessment Result Tool" src="/docs/assets/img/schools/assessment/assessment-result-tool.png">
A medida que vaya introduciendo las notas para un Estudiante y cambie al siguiente alumno, en el backend, el registro de Resultados del Estudiante se creará automáticamente para ese Estudiante.
{next}

View File

@@ -0,0 +1,7 @@
#Escala de calificación
En la escala de calificación, puedes definir varios grados y límites para los estudiantes. Basado en la calificación obtenida por el estudiante en la evaluación, el grado (Grade) será asignado.
<img class="screenshot" alt="Grading Scale" src="/docs/assets/img/schools/assessment/grading-scale.png">
{next}

View File

@@ -0,0 +1,19 @@
#Evaluación
Cada instituto de educación organiza evaluaciones / examenes para evaluar el progreso de sus estudiantes. En ERPNext, puedes gestionar completamente el proceso de evaluación para sus cuentas en ERPNext.
A continuación se muestra el orden en el que debe configurar los masters en el módulo de evaluación.
1. Criterio de Evaluación
2. Grupo de Evaluación
3. Escala de Evaluación
Una vez tengas definido los Grupos de Estudiantes y Cursos, puedes programar una evaluación / examinación creando un Plan de Evaluación.
Basado en el rendimiento del estudiante en la evaluación, puedes ingresar los resultados de la evaluación por un estudiante. Puedes ingresar todos los registros de los estudiantes usando la herramienta de resultados de evaluación. En esta herramienta, en la selecció del Plan de Evaluación, todos los estudiantes (De un grupo de estudiantes) van a ser buscados y mostrados. Puedes rápidamente ingresar los puntos obtenidos por cada estudiante en cada uno de los Criterios de Evaluación en una sola linea.
### Temas
{index}

View File

@@ -0,0 +1,6 @@
assessment_criteria
assessment_group
grading_scale
assessment_plan
assessment_result_tool
assessment_result

View File

@@ -0,0 +1,7 @@
# Admisiones
Esta sección contiene los documentos relacionados a adminisiones de estudiantes.
### Temas
{index}

View File

@@ -0,0 +1,2 @@
student-applicant
program-enrollment

View File

@@ -0,0 +1,7 @@
# Inscripción al Programa
Este formulario te permite inscribir un estudiante a un programa. Un estudiante puede ser inscrito en multiples programas.
<img class="screenshot" alt="Student Applicant Enrollment" src="/docs/assets/img/schools/admission/program-enrollment.png">
{next}

View File

@@ -0,0 +1,28 @@
# Aplicación de Estudiante
Un registro de Aplicación de Estudiante necesita ser creado cuando un estudiante aplica para un programa en su institución.
Puedes Aprobar o Rechazar una aplicación de estudiante. Aceptando una aplicación de un estudiante puedes agregarlos al master de estudiantes.
<img class="screenshot" alt="Student Applicant" src="/docs/assets/img/schools/admission/student-applicant.png">
### Estados de la Aplicación
- Por defecto cuando una aplicación de estudiante es creada en el sistema, el estado de la aplicación es seteado a 'Applied'
- Puedes actualizar el estado a 'Approved' una vez apruebas la aplicación de estudiante para unirse a su institución
- Cuando el estado de la aplicación es actualizada a 'Approved', el botón de 'Inscribir' debería aparecer.
Puedes crear un registro de estudiante usando la aplicación de estudiante e inscribirlos a un programa al presionar el botón de Inscribir
- Una vez el estudiante es creado usando la aplicación de estudiante, el sistema va a setear el estado del documento de aplicación a 'Admitted'
y no te va a permiter cambiar el estado de la aplicación a menos que el estudiante sea eliminado
### Registro de Estudiante
Una vez aprobada una Aplicación de Estudiante, puedes inscribirlo a un programa. Cuando le das click al butón 'Inscribir',
el sistema creará un estudiante usando esa aplicación y le va a redireccionar a el [Formulario de Inscripción al Programa](/docs/user/manual/es/schools/student/program-enrollment.html).
<img class="screenshot" alt="Student Applicant Enrollment" src="/docs/assets/img/schools/admission/student-applicant-enroll.png">
{next}

View File

@@ -0,0 +1,7 @@
# Categoría de Cuota
Todos los tipos diferentes de cuotas que se cobran
<img class="screenshot" alt="Fees Category" src="/docs/assets/img/schools/fees/fee-category.png">
{next}

View File

@@ -0,0 +1,7 @@
# Estructura de Cuota
Una Estructura de Cuota es una plantilla que puede ser usada cuando se hacen registros de cuotas.
<img class="screenshot" alt="Fees Structure" src="/docs/assets/img/schools/fees/fee-structure.png">
{next}

View File

@@ -0,0 +1,8 @@
# Cuotas
Mantiene un registro de todas las cuotas recolectadas de los estudiantes.
La [Estructura de Cuota](/docs/user/manual/es/schools/fees/fee-structure.html) es seleccionada basada en el programa seleccionada y los Términos Académicos.
<img class="screenshot" alt="Fees" src="/docs/assets/img/schools/fees/fees.png">
{next}

View File

@@ -0,0 +1,9 @@
# Cuota
Esta sección contiene todos los documentos relacionado a las 'Cuota'
<img class="screenshot" alt="Fees Section" src="/docs/assets/img/schools/fees/fees-section.png">
### Temas
{index}

View File

@@ -0,0 +1,3 @@
fees
fee-structure
fee-category

View File

@@ -0,0 +1,8 @@
# Schools
Los módulos de School estan diseñados para satisfacer los requerimientos de Escuelas, Colegios e Institutos Educacionales.
<img class="screenshot" alt="Fees Section" src="/docs/assets/img/schools/module.png">
{index}

View File

@@ -0,0 +1,6 @@
student
admission
schedule
fees
setup
assessment

View File

@@ -0,0 +1,25 @@
# Horario de un Curso
El Horario de Curso es el horario de una sesión de un profesor para un Curso en particular.
Puedes ver un resumen del horario del curso en la vista de Calendario.
<img class="screenshot" alt="Course Schedule" src="/docs/assets/img/schools/schedule/course-schedule.png">
### Marcando asistencia
Puedes pasar la asistencia para un grupo de estudiantes usando el Horario de Curso.
<img class="screenshot" alt="Course Schedule Attendance" src="/docs/assets/img/schools/schedule/course-schedule-att.png">
- Para hacer la asistencia, expandir la sección de asistencia.
- Selecciona los estudiantes que estaban presentes para esa sesión.
- Click en el botón de 'Mark Attendance'. El sistema va a crear los registros de asistencia automáticamente.
### Ver Asistencia
Una vez hayas marcado la asistencia usando la sección de asistencia en el Horario de un Curso, esta sección debería estar oculta.
Un botón de Ver Asistencia debería aparecer. Click en el botón para ver todos los registros de asistencia creados para ese Horario de Curso.
<img class="screenshot" alt="Course Schedule Attendance" src="/docs/assets/img/schools/schedule/course-schedule-att-1.png">
{next}

View File

@@ -0,0 +1,8 @@
# Examinación
El registro de examinación puede ser usado para hacer el seguimiento del horario de los examenes y los resultados de los mismos.
<img class="screenshot" alt="Examination" src="/docs/assets/img/schools/schedule/examination.png">
{next}

View File

@@ -0,0 +1,7 @@
# Horario
<img class="screenshot" alt="Schedule Section" src="/docs/assets/img/schools/schedule/schedule-section.png">
### Temas
{index}

View File

@@ -0,0 +1,4 @@
course-schedule
student-attendance
scheduling-tool
examination

View File

@@ -0,0 +1,23 @@
# Herramienta para Horarios
Esta herramienta puede ser usada para crear los Horarios de los Cursos.
<img class="screenshot" alt="Scheduling Tool" src="/docs/assets/img/schools/schedule/scheduling-tool.png">
### Creando Horarios de Cursos
- Selecciona el Grupo de Estudiante para el cual vas a establecer el Horario.
- Seleccione el curso, Aula y un Instructor para el Horario.
- Específica los rangos de fecha desde-hasta para el horario de los cursos.
- Especifíca Fecha Inicio y Fecha Final de un curso(Los Horarios de los cursos van a ser creados dentro de este rango de fechas)
- Espeficíca el dia de la semana en el cual deseas establecer el horario.
- Presiona el botón de 'Schedule Course'
- El sistema va a crear la planificación si el Aula y el Instructor estan disponibles y no hay ningún conflicto con el grupo de estudiantes seleccionados con otros horarios para el mismo grupo.
###Reprogramar Horario
- Si deseas reprogramar el horario de un curso, sigue las instrucciones para crear horarios de cursos.
- Selecciona el checkbox 'Reschedule' y luego da click en el botón 'Schedule Course'.
- El sistema va a eliminar la progración de horario especifícada para ese curso dentro del rango de fecha seleccionado y crearia la nueva planificación de horario para el curso.
{next}

View File

@@ -0,0 +1,7 @@
# Asistencia de Estudiante
Mantiene los registros de la asistencia del estudiante. Los registros de asistencia pueden ser creados sobre los horarios de los cursos (Course Schedules).
<img class="screenshot" alt="Student Attendance" src="/docs/assets/img/schools/schedule/student-attendance.png">
{next}

View File

@@ -0,0 +1,6 @@
# Término Académico
<img class="screenshot" alt="Academic Term" src="/docs/assets/img/schools/setup/academic-term.png">
{next}

View File

@@ -0,0 +1,5 @@
# Año Académico
<img class="screenshot" alt="Academic Year" src="/docs/assets/img/schools/setup/academic-year.png">
{next}

View File

@@ -0,0 +1,5 @@
# Curso
<img class="screenshot" alt="Course" src="/docs/assets/img/schools/setup/course.png">
{next}

View File

@@ -0,0 +1,7 @@
# Configuración
<img class="screenshot" alt="Setup Section" src="/docs/assets/img/schools/setup/setup-section.png">
### Temas
{index}

View File

@@ -0,0 +1,6 @@
course
program
instructor
room
academic-term
academic-year

View File

@@ -0,0 +1,5 @@
# Instructor
<img class="screenshot" alt="Instructor" src="/docs/assets/img/schools/setup/instructor.png">
{next}

View File

@@ -0,0 +1,5 @@
# Programa
<img class="screenshot" alt="Program" src="/docs/assets/img/schools/setup/program.png">
{next}

View File

@@ -0,0 +1,6 @@
# Aula
<img class="screenshot" alt="Room" src="/docs/assets/img/schools/setup/room.png">
{next}

View File

@@ -0,0 +1,7 @@
# Student
Esta sección contiene los documentos relacionados a los estudiantes.
### Temas
{index}

View File

@@ -0,0 +1,5 @@
student
student-log
student-batch
student-group
student-group-creation-tool

View File

@@ -0,0 +1,8 @@
# Lote de Estudiantes
Un lote de estudiantes es una colección de estudiantes desde los Grupos de Estudiantes.
<img class="screenshot" alt="Student" src="/docs/assets/img/schools/student/student-batch.png">
{next}

View File

@@ -0,0 +1,8 @@
# Herramienta para creación de Grupo de Estudiantes
Esta herramienta te permite crear grupos de estudiantes. Puedes especificar multiples parámetros para crearlos.
<img class="screenshot" alt="Student Group Creation Tool" src="/docs/assets/img/schools/student/student-group-creation-tool.png">
{next}

View File

@@ -0,0 +1,8 @@
# Grupo de Estudiante
Un Grupo de Estudiante es una colección de estudiantes tomando el mismo curso. Puedes crear calendarios para los cursos y examinaciones para un Grupo de Estudiante.
Un Grupo de Estudiante necesita ser creado para cada curso en un año o término académico en particular.
<img class="screenshot" alt="Student Group" src="/docs/assets/img/schools/student/student-group.png">
{next}

View File

@@ -0,0 +1,8 @@
# Bitácora de Estudiante (Log)
Puedes crear una nota de una actividad de un estudiante usando la bitácora de estudiante (log)
Los registros de bitágora pueden ser categorizadas como 'General', 'Academic', 'Medical' or 'Achievement'
<img class="screenshot" alt="Student" src="/docs/assets/img/schools/student/student-log.png">
{next}

View File

@@ -0,0 +1,10 @@
# Estudiante
Un estudiante es una persona que se ha registrado en su institución y has aceptado se solicitud de aplicación.
El doctype de Estudiante mantiene los detalles personales de los estudiantes.
Puedes ver todo lo relacionado a un estudiante en particular en esta página. Ejemplo: Pagos, Grupo de Estudiante, etc.
<img class="screenshot" alt="Student" src="/docs/assets/img/schools/student/student.png">
{next}

View File

@@ -50,7 +50,8 @@ calendars = ["Task", "Production Order", "Leave Application", "Sales Order", "Ho
fixtures = ["Web Form"]
website_generators = ["Item Group", "Item", "BOM", "Sales Partner", "Job Opening", "Student Admission"]
website_generators = ["Item Group", "Item", "BOM", "Sales Partner",
"Job Opening", "Student Admission"]
website_context = {
"favicon": "/assets/erpnext/images/favicon.png",
@@ -83,7 +84,7 @@ website_route_rules = [
{"from_route": "/quotations/<path:name>", "to_route": "order",
"defaults": {
"doctype": "Quotation",
"parents": [{"label": _("Quotations"), "route": "quotation"}]
"parents": [{"label": _("Quotations"), "route": "quotations"}]
}
},
{"from_route": "/shipments", "to_route": "Delivery Note"},
@@ -195,7 +196,8 @@ scheduler_events = {
"erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings.send_summary",
"erpnext.stock.doctype.serial_no.serial_no.update_maintenance_status",
"erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards",
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history"
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history",
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
]
}

View File

@@ -1,39 +1,40 @@
QUnit.module('hr');
QUnit.test("Test: Employee [HR]", function (assert) {
assert.expect(3);
assert.expect(4);
let done = assert.async();
let today_date = frappe.datetime.nowdate();
frappe.run_serially([
// let today_date = frappe.datetime.nowdate();
let employee_creation = (name,joining_date,birth_date) => {
frappe.run_serially([
// test employee creation
() => frappe.set_route("List", "Employee", "List"),
() => frappe.new_doc("Employee"),
() => frappe.timeout(1),
() => cur_frm.set_value("employee_name", "Test Employee 1"),
() => cur_frm.set_value("salutation", "Ms"),
() => cur_frm.set_value("company", "Test Company"),
() => cur_frm.set_value("date_of_joining", frappe.datetime.add_months(today_date, -2)), // joined 2 month from now
() => cur_frm.set_value("date_of_birth", frappe.datetime.add_months(today_date, -240)), // age is 20 years
() => cur_frm.set_value("employment_type", "Test Employment type"),
() => cur_frm.set_value("holiday_list", "Test Holiday list"),
() => cur_frm.set_value("branch", "Test Branch"),
() => cur_frm.set_value("department", "Test Department"),
() => cur_frm.set_value("designation", "Test Designation"),
() => frappe.click_button('Add Row'),
() => cur_frm.fields_dict.leave_approvers.grid.grid_rows[0].doc.leave_approver="Administrator",
// save data
() => cur_frm.save(),
() => frappe.timeout(1),
// check name of employee
() => assert.equal("Test Employee 1", cur_frm.doc.employee_name,
'name of employee correctly saved'),
// check auto filled gender according to salutation
() => assert.equal("Female", cur_frm.doc.gender,
'gender correctly saved as per salutation'),
// check auto filled retirement date [60 years from DOB]
() => assert.equal(frappe.datetime.add_months(today_date, 480), cur_frm.doc.date_of_retirement, // 40 years from now
'retirement date correctly saved as per date of birth'),
() => {
frappe.tests.make('Employee', [
{ employee_name: name},
{ salutation: 'Mr'},
{ company: 'Test Company'},
{ date_of_joining: joining_date},
{ date_of_birth: birth_date},
{ employment_type: 'Test Employment Type'},
{ holiday_list: 'Test Holiday List'},
{ branch: 'Test Branch'},
{ department: 'Test Department'},
{ designation: 'Test Designation'}
]);
},
() => frappe.timeout(2),
() => {
assert.ok(cur_frm.get_field('employee_name').value==name,
'Name of an Employee is correctly set');
assert.ok(cur_frm.get_field('gender').value=='Male',
'Gender of an Employee is correctly set');
},
]);
};
frappe.run_serially([
() => employee_creation('Test Employee 1','2017-04-01','1992-02-02'),
() => frappe.timeout(6),
() => employee_creation('Test Employee 3','2017-04-01','1992-02-02'),
() => frappe.timeout(4),
() => done()
]);
});

View File

@@ -1,10 +1,10 @@
QUnit.module('hr');
QUnit.test("Test: Employee attendance tool [HR]", function (assert) {
assert.expect(3);
assert.expect(2);
let done = assert.async();
let today_date = frappe.datetime.nowdate();
let date_of_attendance = frappe.datetime.add_days(today_date, -1); // previous day
let date_of_attendance = frappe.datetime.add_days(today_date, -2); // previous day
frappe.run_serially([
// create employee
@@ -38,11 +38,9 @@ QUnit.test("Test: Employee attendance tool [HR]", function (assert) {
() => frappe.set_route("List", "Attendance", "List"),
() => frappe.timeout(1),
() => {
assert.deepEqual(["Test Employee 2", "Test Employee 1"], [cur_list.data[0].employee_name, cur_list.data[1].employee_name],
"marked attendance correctly saved for both employee");
let marked_attendance = cur_list.data.filter(d => d.attendance_date == date_of_attendance);
assert.equal(marked_attendance.length, 2,
'both the attendance are marked for correct date');
assert.equal(marked_attendance.length, 3,
'all the attendance are marked for correct date');
},
() => done()
]);

View File

@@ -0,0 +1,29 @@
QUnit.module('hr');
QUnit.test("Test: Job Opening [HR]", function (assert) {
assert.expect(2);
let done = assert.async();
frappe.run_serially([
// Job Applicant creation
() => {
frappe.tests.make('Job Applicant', [
{ applicant_name: 'Utkarsh Goswami'},
{ email_id: 'goswamiutkarsh0@gmail.com'},
{ job_title: 'software-developer'},
{ cover_letter: 'Highly skilled in designing, testing, and developing software.'+
' This is just a test.'}
]);
},
() => frappe.timeout(4),
() => frappe.set_route('List','Job Applicant'),
() => frappe.timeout(3),
() => {
assert.ok(cur_list.data.length==1, 'Job Applicant created successfully');
assert.ok(cur_list.data[0].name=='Utkarsh Goswami - goswamiutkarsh0@gmail.com - software-developer',
'Correct job applicant with valid job title');
},
() => done()
]);
});

View File

@@ -0,0 +1,27 @@
QUnit.module('hr');
QUnit.test("Test: Job Opening [HR]", function (assert) {
assert.expect(2);
let done = assert.async();
frappe.run_serially([
// Job Opening creation
() => {
frappe.tests.make('Job Opening', [
{ job_title: 'Software Developer'},
{ description:
'You might be responsible for writing and coding individual'+
' programmes or providing an entirely new software resource.'}
]);
},
() => frappe.timeout(4),
() => frappe.set_route('List','Job Opening'),
() => frappe.timeout(3),
() => {
assert.ok(cur_list.data.length==1, 'Job Opening created successfully');
assert.ok(cur_list.data[0].job_title=='Software Developer', 'Job title Correctly set');
},
() => done()
]);
});

Some files were not shown because too many files have changed in this diff Show More