Compare commits

...

135 Commits

Author SHA1 Message Date
Nabin Hait
77f04e293a Merge branch 'develop' 2015-06-15 10:35:39 +05:30
Nabin Hait
d1d3237784 bumped to version 5.0.24 2015-06-15 11:05:39 +06:00
Nabin Hait
76f0d26f1e Merge pull request #3471 from nabinhait/develop
Hotfix
2015-06-15 10:32:23 +05:30
Nabin Hait
65922d3079 [fix] supplier invoice date can not be after posting date 2015-06-15 10:23:53 +05:30
Nabin Hait
810041cbe3 [fix] Fixed error due to performance upgrade cleanup 2015-06-15 10:20:11 +05:30
Nabin Hait
b9626659ea Merge pull request #3465 from neilLasrado/po
Po
2015-06-15 10:04:36 +05:30
Nabin Hait
e3d13bee36 Merge pull request #3467 from anandpdoshi/anand-june-12
Fixes
2015-06-15 10:03:20 +05:30
Nabin Hait
13bd538aca Merge branch 'develop' 2015-06-14 22:04:51 +05:30
Nabin Hait
d72a24965b bumped to version 5.0.23 2015-06-14 22:34:51 +06:00
Nabin Hait
dc633fe360 Merge pull request #3470 from nabinhait/develop
Performance upgrade in reports and indexing
2015-06-14 22:01:30 +05:30
Nabin Hait
39046d663d [patch] Add index on Account and GL Entry table 2015-06-14 20:59:28 +05:30
Nabin Hait
6b01abe9ad [report][performance] Speed increased by approx 10 times in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement 2015-06-14 20:59:28 +05:30
Anand Doshi
63e4d31aa6 [fix] Task should be mandatory in Time Log only when Project is mentioned but Production Order is not 2015-06-12 18:59:18 -04:00
Anand Doshi
f2a0161709 [fix] Don't create Time Logs against Production Order if Workstation is not specified in Operations 2015-06-12 18:58:36 -04:00
Neil Trini Lasrado
3c1a4a0b9b percent_complete made no-copy in Project 2015-06-12 18:34:08 +05:30
Neil Trini Lasrado
82cc2921d1 Validation added to prevent user from creating salary structure with 'From Date' before employee 'Date of joining' 2015-06-12 18:34:08 +05:30
Nabin Hait
87edd86854 Merge branch 'develop' 2015-06-12 18:06:21 +05:30
Nabin Hait
e37dd77923 bumped to version 5.0.22 2015-06-12 18:36:21 +06:00
Nabin Hait
e4f689184f Merge pull request #3459 from neilLasrado/po
Multiple Fixes.
2015-06-12 17:55:23 +05:30
Nabin Hait
85f825e98c Merge pull request #3463 from nabinhait/develop
multiple issues
2015-06-12 17:48:54 +05:30
Nabin Hait
89592c5180 Load tasks in project for printing purpose 2015-06-12 17:37:28 +05:30
Neil Trini Lasrado
587bd144d5 Added Customers Not Buying Since Long Time against Sales Invoice 2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
1f048b2426 Fixes in Activity Cost 2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
1792ff3be7 Validation added in Purchase Invoice to check if Supplier Invoice Date is greater than Posting Date
Check Supplier Invoice Number Uniqueness setting added to Accounts Settings
Validation added in Purchase Invoice to check Supplier Invoice Number Uniqueness if Check Supplier Invoice Number Uniqueness is enabled in Accounts Settings
2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
fc595064e0 validation added to prevent Delivery Date in Porduction Order to be lesser than Planned Start Date 2015-06-11 18:36:52 +05:30
Nabin Hait
804b4acb9b [fix] Issue fixed in C-Form related to field renaming 2015-06-11 16:56:36 +05:30
Nabin Hait
5c7557914b Removed BOM No from mandatory from Stock Entry against Production Order 2015-06-11 16:50:35 +05:30
Nabin Hait
381a9377d9 Merge branch 'develop' 2015-06-11 16:14:48 +05:30
Nabin Hait
9bdd1aa1ed bumped to version 5.0.21 2015-06-11 16:44:48 +06:00
Nabin Hait
d0df28bfa0 Merge pull request #3458 from nabinhait/develop
[fix] load tasks in project via __setup__ instead of onload function, to return tasks via get_doc
2015-06-11 16:12:05 +05:30
Nabin Hait
1966225450 [fix] load tasks in project via __setup__ instead of onload function, to return tasks via get_doc 2015-06-11 15:31:47 +05:30
Nabin Hait
4cee27eec0 Merge pull request #3446 from anandpdoshi/anand-june-9
POS - search by Item Group
2015-06-10 18:42:14 +05:30
Nabin Hait
c7d4eaee79 Merge pull request #3442 from nabinhait/develop
fixes in stock entry and report
2015-06-10 18:40:42 +05:30
Nabin Hait
43c1a9b502 [fix] Quote url for item image in product listing page 2015-06-10 18:23:17 +05:30
Nabin Hait
b937fac3ce [report] Warehouse column added in 'Ordered Items to be Delivered' report 2015-06-10 18:21:57 +05:30
Nabin Hait
53d94996ad [fix] Query for Against Journal Entry 2015-06-10 18:20:18 +05:30
Anand Doshi
26f6752c1e POS - search by Item Group 2015-06-09 16:33:46 -04:00
Nabin Hait
bb429745c0 [fix] Blank option in naming series 2015-06-09 18:59:51 +05:30
Nabin Hait
909f0c38f1 [report][enhancement] Payment period based on invoice date: show party columns and filter based on party 2015-06-09 18:42:52 +05:30
Nabin Hait
a790ba05f4 [fix] Item name, description should not be overwritten on saving of stock entry 2015-06-09 18:42:52 +05:30
Nabin Hait
11fc4f85d0 Merge branch 'develop' 2015-06-09 15:56:20 +05:30
Nabin Hait
17452a1695 bumped to version 5.0.20 2015-06-09 16:26:20 +06:00
Nabin Hait
7c3d48e353 Merge pull request #3434 from neilLasrado/material-request
Status Indicators fixed in Material Request List
2015-06-09 15:47:46 +05:30
Neil Trini Lasrado
5d288e407c item variants patch removed 2015-06-09 15:46:57 +05:30
Neil Trini Lasrado
f64fae752f fixes 2015-06-09 15:46:57 +05:30
Neil Trini Lasrado
82763f052f Status Indicators fixed in Material Request List 2015-06-09 15:46:57 +05:30
Nabin Hait
bafc73568a Merge pull request #3435 from neilLasrado/barcode
Barcode added to Purchase Receipt
2015-06-09 15:44:09 +05:30
Neil Trini Lasrado
d015195617 fixes in barcode 2015-06-09 15:21:50 +05:30
Neil Trini Lasrado
b2f550ccb3 Barcode added to Purchase Receipt 2015-06-09 15:18:58 +05:30
Nabin Hait
41413af42d Merge pull request #3437 from anandpdoshi/task-close-assignment
[fix] Close assignment (ToDo) when Task status is changed to Closed
2015-06-09 15:00:06 +05:30
Anand Doshi
ec60ebde6f [fix] Close assignment (ToDo) when Task status is changed to Closed 2015-06-08 12:48:11 -04:00
Nabin Hait
ce81a61fe7 Merge branch 'develop' 2015-06-08 14:45:13 +05:30
Nabin Hait
dc76b3fa20 bumped to version 5.0.19 2015-06-08 15:15:13 +06:00
Nabin Hait
828cbee12a Merge pull request #3429 from neilLasrado/quality-inspection
Get Item Details in Quality Inspection.
2015-06-08 14:24:11 +05:30
Nabin Hait
5f5ef16b91 Merge pull request #3430 from nabinhait/develop
Multiple fixes
2015-06-08 14:23:52 +05:30
Nabin Hait
686ef8308a Show item name in item grid view based 'In List View' property 2015-06-08 14:22:56 +05:30
Nabin Hait
b63ad44b10 Book in round-off account upto max 0.05 2015-06-08 14:15:12 +05:30
Nabin Hait
5ef121bc10 get party details only if party exists 2015-06-08 14:15:11 +05:30
Neil Trini Lasrado
42c1836db5 function changed to add fetch 2015-06-08 13:09:11 +05:30
Neil Trini Lasrado
9dbdef3bd5 added code to fetch item name and desc on change of item code 2015-06-08 12:29:12 +05:30
Nabin Hait
9fd42ed2f7 Merge pull request #3428 from nabinhait/develop
[fix] Fiscal year issue due to missing field in Material Request
2015-06-08 12:27:27 +05:30
Nabin Hait
000835c454 [fix] Fiscal year issue due to missing field in Material Request 2015-06-08 12:10:43 +05:30
Nabin Hait
de1f934e22 Merge pull request #3422 from nabinhait/develop
Manufactured qty in Stock Entry
2015-06-08 12:07:47 +05:30
Nabin Hait
7cbd916b00 [fix] Fiscal year issue due to missing field in Material Request 2015-06-08 12:06:33 +05:30
Nabin Hait
56fcf30cb9 [Patch] Update material transferred for manufacturing for existing entries 2015-06-05 18:21:35 +05:30
Nabin Hait
ebbdd772a9 [fix] Validate and update manufactured qty in Stock Entry 2015-06-05 18:21:35 +05:30
Pratik Vyas
6268d83173 Merge branch 'develop' 2015-06-05 15:56:49 +05:30
Pratik Vyas
4599467939 bumped to version 5.0.18 2015-06-05 16:26:49 +06:00
Nabin Hait
d3613479c6 Merge pull request #3421 from nabinhait/develop
pos link and item description
2015-06-05 15:51:03 +05:30
Nabin Hait
6bf301f53c Show item description in grid view based on 'In List View' property 2015-06-05 15:49:25 +05:30
Nabin Hait
27d7f21553 [fix] pos profile link in Start POS page 2015-06-05 15:09:44 +05:30
Nabin Hait
8f87cff4bd Merge pull request #3411 from nabinhait/develop
journal entry against expense claim and bank reco
2015-06-05 14:31:23 +05:30
Nabin Hait
8f39766924 Merge pull request #3419 from neilLasrado/time-log
operation made non mandatory in time log
2015-06-05 14:30:22 +05:30
Neil Trini Lasrado
39669f2717 operation made non mandatory in time log 2015-06-05 12:17:46 +05:30
Nabin Hait
3c1017c43b Removed deprecated page users 2015-06-05 12:15:01 +05:30
Nabin Hait
0b18a2d347 Reset values in tools like Payment Tool 2015-06-05 12:01:29 +05:30
Nabin Hait
6262496e70 [fix] item test case 2015-06-03 18:33:47 +05:30
Nabin Hait
c9963f1805 [fix] journal entry against expense claim: pending amount validation 2015-06-03 18:01:09 +05:30
Nabin Hait
8a2b1bcb97 [fix] bank reconciliation: fetch journal entry order by posting date asc 2015-06-03 18:01:09 +05:30
Pratik Vyas
b8ecf7c757 Merge branch 'develop' 2015-06-03 17:43:38 +05:30
Pratik Vyas
cf89fa2253 bumped to version 5.0.17 2015-06-03 18:13:38 +06:00
Nabin Hait
419c1eb90d Merge pull request #3410 from nabinhait/develop
[fix][patch] force reload web-form-field in portal fixes patch
2015-06-03 17:43:01 +05:30
Nabin Hait
2c214e0362 [fix][patch] force reload web-form-field in portal fixes patch 2015-06-03 17:42:12 +05:30
Nabin Hait
7d04dd0bfd Merge pull request #3408 from williamjmorenor/patch-1
Update Chart of Account for Nicaragua
2015-06-03 17:17:09 +05:30
Nabin Hait
f1371a7ee7 Merge pull request #3409 from nabinhait/develop
Multiple fixes
2015-06-03 17:15:42 +05:30
Nabin Hait
995a78421a [fix] Stock analytics report fixed for fifo stack related to stock reco 2015-06-03 16:44:26 +05:30
Nabin Hait
352187bee6 purchase register fix 2015-06-03 12:06:19 +05:30
Nabin Hait
c6d8121f4a delete fields inline description 2015-06-03 11:24:37 +05:30
Nabin Hait
030ade428b dont reset company on deleting company transactions 2015-06-03 11:24:37 +05:30
Nabin Hait
c87595b2da show item description in item grid view if marked for 'In List View' 2015-06-03 11:24:37 +05:30
Nabin Hait
42f2674cba dynamic link in quotation item 2015-06-03 11:24:37 +05:30
Nabin Hait
5359f2651a [fix] sales register report 2015-06-03 11:24:37 +05:30
William Moreno
42dcffdad4 Update Chart of Account for Nicaragua
Hi

The Law 891 reform some taxes rates, please update the Chart of Account for Nicaragua so it can reflect the new tax rates.
2015-06-02 16:48:47 -06:00
Anand Doshi
f7c1743b28 [hotfix] cart - get_address_docs 2015-06-02 15:20:25 -04:00
Anand Doshi
64aa6620be [hotfix] portal fixes patch 2015-06-02 11:53:17 -04:00
Rushabh Mehta
ed43f8015c [lang] let locale be en in setup wizard (?) 2015-06-02 12:31:03 +05:30
Rushabh Mehta
d3fe7ec858 [cleanup] customer not buying since long time report 2015-06-02 12:21:17 +05:30
Rushabh Mehta
c8b406d050 [fix] duplicate status for Submitted, Cancelled 2015-06-02 12:17:14 +05:30
Rushabh Mehta
2aa577f110 [hot] patch-fix 2015-06-02 11:12:25 +05:30
Pratik Vyas
f06d175061 Merge branch 'develop' 2015-06-02 10:45:28 +05:30
Pratik Vyas
74b2116adb bumped to version 5.0.16 2015-06-02 11:15:28 +06:00
Rushabh Mehta
2204d0af94 Merge pull request #3397 from rmehta/portal-fixes
Portal fixes
2015-06-02 10:42:59 +05:30
Pratik Vyas
b8a568765d Update translations 2015-06-01 23:49:15 +05:30
Rushabh Mehta
cf29f6468d [minor] add attachment to issue via portal: 2015-06-01 17:47:03 +05:30
Rushabh Mehta
aded46d33e [fix] product search in new block header_actions 2015-06-01 17:23:42 +05:30
Pratik Vyas
b8dd046c84 Merge branch 'develop' 2015-06-01 17:17:46 +05:30
Pratik Vyas
e5fa5e6111 bumped to version 5.0.15 2015-06-01 17:47:46 +06:00
Nabin Hait
b89cf1b3ec Merge pull request #3396 from nabinhait/develop
item table print template
2015-06-01 17:16:00 +05:30
Rushabh Mehta
a33d468d30 [fixes] portal, issues, addresses etc 2015-06-01 17:15:42 +05:30
Nabin Hait
e481a211b1 item table print template 2015-06-01 17:12:55 +05:30
Rushabh Mehta
ca23b5ecfd Merge pull request #3395 from nabinhait/develop
GL Entries for Journal Entries with multiple Party
2015-06-01 16:35:36 +05:30
Nabin Hait
11190268ab [fix][patch] GL Entries for Journal Entries with multiple Party, merge entries considering party 2015-06-01 16:21:25 +05:30
Nabin Hait
a19150ddaf default account's custom query in company 2015-06-01 15:32:57 +05:30
Nabin Hait
c17dff4b01 default account's custom query in company 2015-06-01 15:32:57 +05:30
Pratik Vyas
47fe136d15 Merge branch 'develop' 2015-06-01 14:51:17 +05:30
Pratik Vyas
8f25402dce bumped to version 5.0.14 2015-06-01 15:21:17 +06:00
Nabin Hait
a9165744e2 Merge pull request #3385 from nabinhait/develop
In standard print format, item name will now honour 'Print Hide' property
2015-06-01 14:03:11 +05:30
Nabin Hait
3ebfad7115 minor fixes 2015-06-01 14:01:56 +05:30
Nabin Hait
c7ef8dda79 [fix] Pricing Rule based on qty 2015-06-01 14:01:56 +05:30
Nabin Hait
4a6c178795 On selection of item, set default qty as 1 2015-06-01 14:01:56 +05:30
Nabin Hait
8908543a9c In standard print format, item name will now honour 'Print Hide' property 2015-06-01 14:01:56 +05:30
Rushabh Mehta
065badc54b [minor] move buttons from sales invoice to toolbar 2015-05-31 10:36:47 +05:30
Nabin Hait
cd2798368b Merge pull request #3384 from rmehta/journal-entry-ux
[minor] journal entry, copy over party details to new row and automatically set difference
2015-05-29 17:09:53 +05:30
Rushabh Mehta
2c30acdcb2 [minor] journal entry, copy over party details to new row and automatically set difference 2015-05-29 16:33:36 +05:30
Rushabh Mehta
4a4a6594d1 [minor] [refactor] 2015-05-29 15:56:40 +05:30
Pratik Vyas
e3035a593c Merge branch 'develop' 2015-05-29 14:25:23 +05:30
Pratik Vyas
587dde0044 bumped to version 5.0.13 2015-05-29 14:55:23 +06:00
Pratik Vyas
b6d13ef5b7 Add changelog 2015-05-29 14:24:39 +05:30
Rushabh Mehta
a3e9dbbcc3 Merge pull request #3374 from nabinhait/develop
Make gl entry for rounded-off amount
2015-05-29 14:20:20 +05:30
Nabin Hait
80069a6379 Book gl entry automatically due to rounding loss with test cases 2015-05-29 10:39:09 +05:30
Nabin Hait
98c515fe7d replace 'entries' by 'items' in custom print formats and scripts 2015-05-29 10:39:09 +05:30
Nabin Hait
6ee8c545e3 [fix] gross profit report 2015-05-29 10:39:09 +05:30
Nabin Hait
3c67146e4b Make gl entry for rounded-off amount 2015-05-29 10:39:09 +05:30
Nabin Hait
e2c200a91e Make gl entry for rounded-off amount 2015-05-29 10:39:09 +05:30
Nabin Hait
d9d5925f14 [fix] BOM item validation in lower case 2015-05-29 10:39:09 +05:30
144 changed files with 2595 additions and 2457 deletions

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '5.0.12'
__version__ = '5.0.24'

View File

@@ -35,7 +35,7 @@
"permlevel": 0,
"read_only": 1,
"reqd": 1,
"search_index": 1
"search_index": 0
},
{
"default": "0",
@@ -44,7 +44,7 @@
"label": "Is Group",
"permlevel": 0,
"precision": "",
"search_index": 1
"search_index": 0
},
{
"fieldname": "company",
@@ -57,7 +57,7 @@
"permlevel": 0,
"read_only": 1,
"reqd": 1,
"search_index": 1
"search_index": 0
},
{
"fieldname": "root_type",
@@ -101,7 +101,7 @@
"label": "Account Type",
"oldfieldname": "account_type",
"oldfieldtype": "Select",
"options": "\nBank\nCash\nTax\nChargeable\nWarehouse\nReceivable\nPayable\nEquity\nFixed Asset\nCost of Goods Sold\nExpense Account\nIncome Account\nStock Received But Not Billed\nExpenses Included In Valuation\nStock Adjustment\nStock\nTemporary",
"options": "\nBank\nCash\nTax\nChargeable\nWarehouse\nReceivable\nPayable\nEquity\nFixed Asset\nCost of Goods Sold\nExpense Account\nRound Off\nIncome Account\nStock Received But Not Billed\nExpenses Included In Valuation\nStock Adjustment\nStock\nTemporary",
"permlevel": 0,
"search_index": 0
},
@@ -147,7 +147,8 @@
"label": "Lft",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "rgt",
@@ -156,7 +157,8 @@
"label": "Rgt",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "old_parent",
@@ -171,7 +173,7 @@
"icon": "icon-money",
"idx": 1,
"in_create": 0,
"modified": "2015-04-27 20:07:37.147184",
"modified": "2015-06-14 20:57:55.471334",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",

View File

@@ -1,6 +1,6 @@
{
"country_code": "ni",
"name": "Catalogo de Cuentas",
"name": "Catalogo de Cuentas Nicaragua",
"is_active": "Yes",
"tree": {
"Activo": {
@@ -72,7 +72,7 @@
"IVA Acreditable por Importaciones": {
"account_type": "Tax"
},
"IVA Acreditable por Prestacion de Servicios": {
"IVA Acreditable por Prestacion de Servicios y Uso y Goce de Bienes": {
"account_type": "Tax"
},
"Acreditacion Proporcional": {}
@@ -229,11 +229,19 @@
"Impuesto al Valor Agregado por Pagar": {
"account_type": "Tax"
},
"Impuesto sobre la Renta": {
"Impuesto sobre la Renta por Actividades Economicas": {
"account_type": "Tax"
},
"Impuestos Municipales": {
"account_type": "Tax"
"Impuesto Municipal Sobre Ingresos": {
"account_type": "Tax"
},
"Recoleccion Basura": {
"account_type": "Tax"
},
"Matricula Municipal": {
"account_type": "Tax"
}
}
},
"Retenciones por Pagar": {
@@ -241,7 +249,13 @@
"Retencion Rentas del Trabajo Tarifa Progresiva": {
"account_type": "Tax"
},
"Retencion Definitiva por Rentas del Trabajo": {
"Retencion Definitiva 10% por Rentas del Trabajo - Indemnizacion Adicional": {
"account_type": "Tax"
},
"Retencion Definitiva 12.5% por Rentas del Trabajo - Dietas": {
"account_type": "Tax"
},
"Retencion Definitiva 15% por Rentas del Trabajo - No Residentes": {
"account_type": "Tax"
}
},
@@ -258,11 +272,26 @@
"Retencion 5% compra Madera en Rollo": {
"account_type": "Tax"
},
"Retencion Definitiva 1.5% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Retencion Definitiva 3% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Retencion Definitiva 10% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Retencion Definitiva 15% Actividades Economicas No Residentes": {
"account_type": "Tax"
},
"Otras Retenciones 10%": {
"account_type": "Tax"
}
},
"Rentas y Ganancias de Capital": {
"Retencion Defintiva 15% por Rentas de Capital": {
"account_type": "Tax"
},
"Retencion Defintiva 10% por Rentas de Capital": {
"account_type": "Tax"
},
@@ -272,10 +301,16 @@
"Retencion Definitiva 10% por Ganancia de Capital": {
"account_type": "Tax"
},
"Retencion Definitiva Actividades Economicas No Residentes": {
"Retencion Definitiva 0.25% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retencion Definitiva Transacciones Bursatiles": {
"Retencion Definitiva 1% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retencion Definitiva 1.5% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retencion Definitiva 2% Transacciones Bursatiles": {
"account_type": "Tax"
},
"Retenciones Defintiva 5% Fondos de Inversion": {

View File

@@ -117,8 +117,8 @@ def get():
_("Print and Stationary"): {
"account_type": "Expense Account"
},
_("Rounded Off"): {
"account_type": "Expense Account"
_("Round Off"): {
"account_type": "Round Off"
},
_("Salary"): {
"account_type": "Expense Account"

View File

@@ -4,6 +4,13 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness",
"permlevel": 0,
"precision": ""
},
{
"default": "1",
"description": "If enabled, the system will post accounting entries for inventory automatically.",
@@ -43,7 +50,7 @@
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:34.163902",
"modified": "2015-06-11 06:06:34.047890",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -2,6 +2,10 @@
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Bank Reconciliation", {
refresh: function(frm) {
frm.disable_save();
},
update_clearance_date: function(frm) {
return frappe.call({
method: "update_details",
@@ -33,5 +37,4 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) {
cur_frm.set_value("from_date", frappe.datetime.month_start());
cur_frm.set_value("to_date", frappe.datetime.month_end());
}
}

View File

@@ -25,7 +25,8 @@ class BankReconciliation(Document):
where
t2.parent = t1.name and t2.account = %s
and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1
and ifnull(t1.is_opening, 'No') = 'No' %s""" %
and ifnull(t1.is_opening, 'No') = 'No' %s
order by t1.posting_date""" %
('%s', '%s', '%s', condition), (self.bank_account, self.from_date, self.to_date), as_dict=1)
self.set('journal_entries', [])

View File

@@ -54,7 +54,7 @@ class CForm(Document):
frappe.throw(_("Please enter atleast 1 invoice in the table"))
def set_total_invoiced_amount(self):
total = sum([flt(d.base_grand_total) for d in self.get('invoices')])
total = sum([flt(d.grand_total) for d in self.get('invoices')])
frappe.db.set(self, 'total_invoiced_amount', total)
def get_invoice_details(self, invoice_no):

View File

@@ -48,7 +48,8 @@
"fieldtype": "Dynamic Link",
"label": "Party",
"options": "party_type",
"permlevel": 0
"permlevel": 0,
"search_index": 1
},
{
"fieldname": "cost_center",
@@ -192,7 +193,7 @@
"icon": "icon-list",
"idx": 1,
"in_create": 1,
"modified": "2015-04-27 20:32:48.246818",
"modified": "2015-06-14 20:57:19.800276",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -0,0 +1,25 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, unittest
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
class TestGLEntry(unittest.TestCase):
def test_round_off_entry(self):
frappe.db.set_value("Company", "_Test Company", "round_off_account", "_Test Write Off - _TC")
frappe.db.set_value("Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", 100, "_Test Cost Center - _TC", submit=False)
jv.get("accounts")[0].debit = 100.01
jv.flags.ignore_validate = True
jv.submit()
round_off_entry = frappe.db.sql("""select name from `tabGL Entry`
where voucher_type='Journal Entry' and voucher_no = %s
and account='_Test Write Off - _TC' and cost_center='_Test Cost Center - _TC'
and ifnull(debit, 0) = 0 and ifnull(credit, 0) = '.01'""", jv.name)
self.assertTrue(round_off_entry)

View File

@@ -4,7 +4,7 @@
frappe.provide("erpnext.accounts");
frappe.require("assets/erpnext/js/utils.js");
erpnext.accounts.JournalVoucher = frappe.ui.form.Controller.extend({
erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
onload: function() {
this.load_defaults();
this.setup_queries();
@@ -130,10 +130,31 @@ erpnext.accounts.JournalVoucher = frappe.ui.form.Controller.extend({
cur_frm.cscript.update_totals(me.frm.doc);
}
});
}
},
accounts_add: function(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function(i, d) {
if(d.account && d.party && d.party_type) {
row.account = d.account;
row.party = d.party;
row.party_type = d.party_type;
}
});
// set difference
if(doc.difference) {
if(doc.difference > 0) {
row.credit = doc.difference;
} else {
row.debit = -doc.difference;
}
}
},
});
cur_frm.script_manager.make(erpnext.accounts.JournalVoucher);
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
cur_frm.cscript.refresh = function(doc) {
erpnext.toggle_naming_series();

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, cint
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
from frappe import msgprint, _, scrub
from erpnext.setup.utils import get_company_currency
from erpnext.controllers.accounts_controller import AccountsController
@@ -81,7 +81,8 @@ class JournalEntry(AccountsController):
frappe.throw(_("Row {0}: Party Type and Party is only applicable against Receivable / Payable account").format(d.idx))
def check_credit_limit(self):
customers = list(set([d.party for d in self.get("accounts") if d.party_type=="Customer" and flt(d.debit) > 0]))
customers = list(set([d.party for d in self.get("accounts")
if d.party_type=="Customer" and d.party and flt(d.debit) > 0]))
if customers:
from erpnext.selling.doctype.customer.customer import check_credit_limit
for customer in customers:
@@ -427,12 +428,11 @@ class JournalEntry(AccountsController):
def validate_expense_claim(self):
for d in self.accounts:
if d.against_expense_claim:
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim", d.against_expense_claim,
("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = cint(sanctioned_amount) - cint(reimbursed_amount)
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim",
d.against_expense_claim, ("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
if d.debit > pending_amount:
frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. \
Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
def validate_credit_debit_note(self):
if self.stock_entry:
@@ -458,11 +458,11 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
if voucher_type=="Bank Entry":
account = frappe.db.get_value("Company", company, "default_bank_account")
if not account:
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank"})
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank", "is_group": 0})
elif voucher_type=="Cash Entry":
account = frappe.db.get_value("Company", company, "default_cash_account")
if not account:
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash"})
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash", "is_group": 0})
if account:
return {
@@ -538,15 +538,13 @@ def get_opening_accounts(company):
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("party"):
return []
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and jv_detail.party = %s
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
and ifnull(jv_detail.against_jv, '') = '' )
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
(filters["account"], filters["party"], "%{0}%".format(txt), start, page_len))
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
@frappe.whitelist()
def get_outstanding(args):

View File

@@ -44,6 +44,10 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
});
},
refresh: function() {
this.frm.disable_save();
},
party: function() {
var me = this

View File

@@ -32,6 +32,7 @@ frappe.ui.form.on("Payment Tool", "onload", function(frm) {
});
frappe.ui.form.on("Payment Tool", "refresh", function(frm) {
frm.disable_save();
frappe.ui.form.trigger("Payment Tool", "party_type");
});

View File

@@ -312,7 +312,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-02-21 03:59:08.154966",
"modified": "2015-06-05 11:17:33.843334",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Tool",

View File

@@ -205,9 +205,9 @@ def get_pricing_rules(args):
def filter_pricing_rules(args, pricing_rules):
# filter for qty
if pricing_rules and args.get("qty"):
pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty)
and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
if pricing_rules:
pricing_rules = filter(lambda x: (flt(args.get("qty"))>=flt(x.min_qty)
and (flt(args.get("qty"))<=x.max_qty if x.max_qty else True)), pricing_rules)
# find pricing rule with highest priority
if pricing_rules:

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint, formatdate, flt
from frappe.utils import cint, formatdate, flt, getdate
from frappe import msgprint, _, throw
from erpnext.setup.utils import get_company_currency
import frappe.defaults
@@ -39,6 +39,7 @@ class PurchaseInvoice(BuyingController):
self.po_required()
self.pr_required()
self.validate_supplier_invoice()
self.check_active_purchase_items()
self.check_conversion_rate()
self.validate_credit_to_acc()
@@ -385,6 +386,16 @@ class PurchaseInvoice(BuyingController):
project.update_purchase_costing()
project.save()
project_list.append(d.project_name)
def validate_supplier_invoice(self):
if self.bill_date:
if getdate(self.bill_date) > getdate(self.posting_date):
frappe.throw("Supplier Invoice Date cannot be greater than Posting Date")
if self.bill_no:
if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no, "fiscal_year": self.fiscal_year})
if pi:
frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))
@frappe.whitelist()
def get_expense_account(doctype, txt, searchfield, start, page_len, filters):

View File

@@ -40,7 +40,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -452,7 +452,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:16.341373",
"modified": "2015-06-02 14:18:56.294949",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -7,6 +7,7 @@ import frappe
@frappe.whitelist()
def get_items(price_list, sales_or_purchase, item=None):
condition = ""
order_by = ""
args = {"price_list": price_list}
if sales_or_purchase == "Sales":
@@ -30,16 +31,25 @@ def get_items(price_list, sales_or_purchase, item=None):
item_code[0]["barcode"] = item
return item_code
condition += " and (CONCAT(i.name, i.item_name) like %(name)s or (i.variant_of like %(name)s))"
condition += " and ((CONCAT(i.name, i.item_name) like %(name)s) or (i.variant_of like %(name)s) or (i.item_group like %(name)s))"
order_by = """if(locate(%(_name)s, i.name), locate(%(_name)s, i.name), 99999),
if(locate(%(_name)s, i.item_name), locate(%(_name)s, i.item_name), 99999),
if(locate(%(_name)s, i.variant_of), locate(%(_name)s, i.variant_of), 99999),
if(locate(%(_name)s, i.item_group), locate(%(_name)s, i.item_group), 99999),"""
args["name"] = "%%%s%%" % item
args["_name"] = item.replace("%", "")
# locate function is used to sort by closest match from the beginning of the value
return frappe.db.sql("""select i.name, i.item_name, i.image,
item_det.price_list_rate, item_det.currency
from `tabItem` i LEFT JOIN
(select item_code, price_list_rate, currency from
`tabItem Price` where price_list=%s) item_det
`tabItem Price` where price_list=%(price_list)s) item_det
ON
(item_det.item_code=i.name or item_det.item_code=i.variant_of)
where
ifnull(i.has_variants, 0) = 0 and
%s""" % ('%(price_list)s', condition), args, as_dict=1)
{condition}
order by
{order_by}
i.name""".format(condition=condition, order_by=order_by), args, as_dict=1)

View File

@@ -65,7 +65,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
});
if(!from_delivery_note) {
cur_frm.page.add_menu_item(__('Make Delivery'), cur_frm.cscript['Make Delivery Note'], "icon-truck")
cur_frm.add_custom_button(__('Make Delivery'), cur_frm.cscript['Make Delivery Note'], "icon-truck")
}
}
@@ -75,14 +75,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
// Show buttons only when pos view is active
if (doc.docstatus===0 && !cur_frm.page.current_view_name!=="pos") {
if (cint(doc.docstatus==0) && cur_frm.page.current_view_name!=="pos") {
cur_frm.cscript.sales_order_btn();
cur_frm.cscript.delivery_note_btn();
}
},
sales_order_btn: function() {
this.$sales_order_btn = cur_frm.page.add_menu_item(__('From Sales Order'),
this.$sales_order_btn = cur_frm.add_custom_button(__('From Sales Order'),
function() {
frappe.model.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
@@ -99,7 +99,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
delivery_note_btn: function() {
this.$delivery_note_btn = cur_frm.page.add_menu_item(__('From Delivery Note'),
this.$delivery_note_btn = cur_frm.add_custom_button(__('From Delivery Note'),
function() {
frappe.model.map_current_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",

View File

@@ -58,7 +58,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -505,7 +505,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.645114",
"modified": "2015-06-02 14:18:45.176726",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import flt, cstr
from frappe import _
from frappe.model.meta import get_field_precision
from erpnext.accounts.utils import validate_expense_against_budget
@@ -55,28 +56,23 @@ def merge_similar_entries(gl_map):
def check_if_in_list(gle, gl_map):
for e in gl_map:
if e.account == gle.account and \
cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == \
cstr(gle.get('against_voucher_type')) \
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')):
return e
if e.account == gle.account \
and cstr(e.get('party_type'))==cstr(gle.get('party_type')) \
and cstr(e.get('party'))==cstr(gle.get('party')) \
and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')):
return e
def save_entries(gl_map, adv_adj, update_outstanding):
validate_account_for_auto_accounting_for_stock(gl_map)
total_debit = total_credit = 0.0
round_off_debit_credit(gl_map)
for entry in gl_map:
make_entry(entry, adv_adj, update_outstanding)
# check against budget
validate_expense_against_budget(entry)
# update total debit / credit
total_debit += flt(entry.debit)
total_credit += flt(entry.credit)
validate_total_debit_credit(total_debit, total_credit, gl_map)
def make_entry(args, adv_adj, update_outstanding):
args.update({"doctype": "GL Entry"})
gle = frappe.get_doc(args)
@@ -85,10 +81,6 @@ def make_entry(args, adv_adj, update_outstanding):
gle.run_method("on_update_with_args", adv_adj, update_outstanding)
gle.submit()
def validate_total_debit_credit(total_debit, total_credit, gl_map):
if abs(total_debit - total_credit) > 0.005:
frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.").format(gl_map[0].voucher_type, gl_map[0].voucher_no, total_debit - total_credit))
def validate_account_for_auto_accounting_for_stock(gl_map):
if gl_map[0].voucher_type=="Journal Entry":
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
@@ -96,7 +88,54 @@ def validate_account_for_auto_accounting_for_stock(gl_map):
for entry in gl_map:
if entry.account in aii_accounts:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions").format(entry.account), StockAccountInvalidTransaction)
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(entry.account), StockAccountInvalidTransaction)
def round_off_debit_credit(gl_map):
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
currency=frappe.db.get_value("Company", gl_map[0].company, "default_currency", cache=True))
debit_credit_diff = 0.0
for entry in gl_map:
entry.debit = flt(entry.debit, precision)
entry.credit = flt(entry.credit, precision)
debit_credit_diff += entry.debit - entry.credit
debit_credit_diff = flt(debit_credit_diff, precision)
if abs(debit_credit_diff) >= (5.0 / (10**precision)):
frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.")
.format(gl_map[0].voucher_type, gl_map[0].voucher_no, debit_credit_diff))
elif abs(debit_credit_diff) >= (1.0 / (10**precision)):
make_round_off_gle(gl_map, debit_credit_diff)
def make_round_off_gle(gl_map, debit_credit_diff):
round_off_account, round_off_cost_center = frappe.db.get_value("Company", gl_map[0].company,
["round_off_account", "round_off_cost_center"]) or [None, None]
if not round_off_account:
frappe.throw(_("Please mention Round Off Account in Company"))
if not round_off_cost_center:
frappe.throw(_("Please mention Round Off Cost Center in Company"))
round_off_gle = frappe._dict()
for k in ["voucher_type", "voucher_no", "company",
"posting_date", "remarks", "fiscal_year", "is_opening"]:
round_off_gle[k] = gl_map[0][k]
round_off_gle.update({
"account": round_off_account,
"debit": abs(debit_credit_diff) if debit_credit_diff < 0 else 0,
"credit": debit_credit_diff if debit_credit_diff > 0 else 0,
"cost_center": round_off_cost_center,
"party_type": None,
"party": None,
"against_voucher_type": None,
"against_voucher": None
})
gl_map.append(round_off_gle)
def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,

View File

@@ -9,7 +9,7 @@
<button class="btn btn-primary btn-lg">{%= __("Start") %}</button>
</p>
<p class="pos-setting-message hide">
<a class="btn btn-default btn-sm" href="#Form/POS Setting/New POS Setting">
{%= __("Make new POS Setting") %}</a>
<a class="btn btn-default btn-sm" href="#Form/POS Profile/New POS Profile">
{%= __("Make new POS Profile") %}</a>
</p>
</div>

View File

@@ -16,12 +16,16 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
if not party:
return {}
if not frappe.db.exists(party_type, party):
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
return _get_party_details(party, account, party_type,
company, posting_date, price_list, currency, doctype)
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, doctype))
party = out[party_type.lower()]

View File

@@ -51,7 +51,7 @@ class ReceivablePayableReport(object):
currency_precision = get_currency_precision() or 2
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
voucher_details = self.get_voucher_details()
voucher_details = self.get_voucher_details(args.get("party_type"))
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
@@ -153,23 +153,26 @@ class ReceivablePayableReport(object):
return self.party_map
def get_voucher_details(self):
def get_voucher_details(self, party_type):
voucher_details = frappe._dict()
if party_type == "Customer":
for si in frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(si.name, si)
for si in frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(si.name, si)
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(pi.name, pi)
if party_type == "Supplier":
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(pi.name, pi)
return voucher_details
def get_gl_entries(self, party_type):
if not hasattr(self, "gl_entries"):
conditions, values = self.prepare_conditions(party_type)
self.gl_entries = frappe.db.sql("""select * from `tabGL Entry`
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party, debit, credit,
voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry`
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
.format(conditions), values, as_dict=True)
@@ -187,7 +190,7 @@ class ReceivablePayableReport(object):
if self.filters.get(party_type_field):
conditions.append("party=%s")
values.append(self.filters.get(party_type_field))
values.append(self.filters.get(party_type_field))
return " and ".join(conditions), values

View File

@@ -83,7 +83,7 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
calculate_values(accounts, gl_entries_by_account, period_list)
calculate_values(accounts_by_name, gl_entries_by_account, period_list)
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
out = prepare_data(accounts, balance_must_be, period_list)
@@ -92,16 +92,14 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
return out
def calculate_values(accounts, gl_entries_by_account, period_list):
for d in accounts:
for name in ([d.name] + (d.collapsed_children or [])):
for entry in gl_entries_by_account.get(name, []):
for period in period_list:
entry.posting_date = getdate(entry.posting_date)
# check if posting date is within the period
if entry.posting_date <= period.to_date:
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
def calculate_values(accounts_by_name, gl_entries_by_account, period_list):
for entries in gl_entries_by_account.values():
for entry in entries:
d = accounts_by_name.get(entry.account)
for period in period_list:
# check if posting date is within the period
if entry.posting_date <= period.to_date:
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
@@ -159,22 +157,8 @@ def add_total_row(out, balance_must_be, period_list):
out.append({})
def get_accounts(company, root_type):
# root lft, rgt
root_account = frappe.db.sql("""select lft, rgt from `tabAccount`
where company=%s and root_type=%s and ifnull(parent_account, '') = ''
order by lft limit 1""",
(company, root_type), as_dict=True)
if not root_account:
return None
lft, rgt = root_account[0].lft, root_account[0].rgt
accounts = frappe.db.sql("""select * from `tabAccount`
where company=%(company)s and lft >= %(lft)s and rgt <= %(rgt)s order by lft""",
{ "company": company, "lft": lft, "rgt": rgt }, as_dict=True)
return accounts
return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
def filter_accounts(accounts, depth=10):
parent_children_map = {}
@@ -196,14 +180,6 @@ def filter_accounts(accounts, depth=10):
filtered_accounts.append(child)
add_to_list(child.name, level + 1)
else:
# include all children at level lower than the depth
parent_account = accounts_by_name[parent]
parent_account["collapsed_children"] = []
for d in accounts:
if d.lft > parent_account.lft and d.rgt < parent_account.rgt:
parent_account["collapsed_children"].append(d.name)
add_to_list(None, 0)
return filtered_accounts, accounts_by_name
@@ -234,7 +210,7 @@ def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closi
if from_date:
additional_conditions.append("and posting_date >= %(from_date)s")
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s

View File

@@ -66,7 +66,7 @@ def get_gl_entries(filters):
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
voucher_type, voucher_no, cost_center, remarks, is_opening, against
voucher_type, voucher_no, cost_center, remarks, against
from `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condition}
@@ -91,6 +91,9 @@ def get_conditions(filters):
if filters.get("party"):
conditions.append("party=%(party)s")
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
conditions.append("posting_date >=%(from_date)s")
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")
@@ -148,14 +151,15 @@ def initialize_gle_map(gl_entries):
def get_accountwise_gle(filters, gl_entries, gle_map):
opening, total_debit, total_credit = 0, 0, 0
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
for gle in gl_entries:
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
if gle.posting_date < getdate(filters.from_date):
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
and gle.posting_date < from_date:
gle_map[gle.account].opening += amount
if filters.get("account") or filters.get("party"):
opening += amount
elif gle.posting_date <= getdate(filters.to_date):
elif gle.posting_date <= to_date:
gle_map[gle.account].entries.append(gle)
gle_map[gle.account].total_debit += flt(gle.debit, 3)
gle_map[gle.account].total_credit += flt(gle.credit, 3)

View File

@@ -14,7 +14,7 @@ def execute(filters=None):
source = gross_profit_data.grouped_data if filters.get("group_by") != "Invoice" else gross_profit_data.data
group_wise_columns = frappe._dict({
"invoice": ["name", "posting_date", "posting_time", "item_code", "item_name", "brand", "description", \
"invoice": ["parent", "customer", "posting_date", "posting_time", "item_code", "item_name", "brand", "description", \
"warehouse", "qty", "base_rate", "buying_rate", "base_amount",
"buying_amount", "gross_profit", "gross_profit_percent", "project"],
"item_code": ["item_code", "item_name", "brand", "description", "warehouse", "qty", "base_rate",
@@ -50,7 +50,7 @@ def execute(filters=None):
def get_columns(group_wise_columns, filters):
columns = []
column_map = frappe._dict({
"name": _("Sales Invoice") + ":Link/Sales Invoice:120",
"parent": _("Sales Invoice") + ":Link/Sales Invoice:120",
"posting_date": _("Posting Date") + ":Date",
"posting_time": _("Posting Time"),
"item_code": _("Item Code") + ":Link/Item",
@@ -183,8 +183,6 @@ class GrossProfitGenerator(object):
my_sle = self.sle.get((item_code, row.warehouse))
for i, sle in enumerate(my_sle):
# find the stock valution rate from stock ledger entry
print sle.voucher_type, row.parenttype, sle.voucher_no, row.parent, \
sle.voucher_detail_no, row.item_row
if sle.voucher_type == row.parenttype and row.parent == sle.voucher_no and \
sle.voucher_detail_no == row.item_row:
previous_stock_value = len(my_sle) > i+1 and \

View File

@@ -3,6 +3,14 @@
frappe.query_reports["Payment Period Based On Invoice Date"] = {
"filters": [
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("company")
},
{
fieldname: "from_date",
label: __("From Date"),
@@ -23,27 +31,28 @@ frappe.query_reports["Payment Period Based On Invoice Date"] = {
default: "Incoming"
},
{
fieldname:"account",
label: __("Account"),
fieldtype: "Link",
options: "Account",
get_query: function() {
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Link",
"options": "DocType",
"get_query": function() {
return {
query: "erpnext.controllers.queries.get_account_list",
filters: {
"report_type": "Balance Sheet",
company: frappe.query_report.filters_by_name.company.get_value()
}
filters: {"name": ["in", ["Customer", "Supplier"]]}
}
}
},
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("company")
"fieldname":"party",
"label": __("Party"),
"fieldtype": "Dynamic Link",
"get_options": function() {
var party_type = frappe.query_report.filters_by_name.party_type.get_value();
var party = frappe.query_report.filters_by_name.party.get_value();
if(party && !party_type) {
frappe.throw(__("Please select Party Type first"));
}
return party_type;
}
},
]
}

View File

@@ -20,16 +20,16 @@ def execute(filters=None):
for d in entries:
if d.against_voucher:
against_date = d.against_voucher and invoice_posting_date_map[d.against_voucher] or ""
outstanding_amount = flt(d.debit) or -1 * flt(d.credit)
payment_amount = flt(d.debit) or -1 * flt(d.credit)
else:
against_date = d.against_invoice and invoice_posting_date_map[d.against_invoice] or ""
outstanding_amount = flt(d.credit) or -1 * flt(d.debit)
payment_amount = flt(d.credit) or -1 * flt(d.debit)
row = [d.name, d.account, d.posting_date, d.against_voucher or d.against_invoice,
row = [d.name, d.party_type, d.party, d.posting_date, d.against_voucher or d.against_invoice,
against_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
if d.against_voucher or d.against_invoice:
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, outstanding_amount)
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, payment_amount)
else:
row += ["", "", "", "", ""]
@@ -38,7 +38,8 @@ def execute(filters=None):
return columns, data
def get_columns():
return [_("Journal Entry") + ":Link/Journal Entry:140", _("Account") + ":Link/Account:140",
return [_("Journal Entry") + ":Link/Journal Entry:140",
_("Party Type") + ":Link/DocType:100", _("Party") + ":Dynamic Link/party_type:140",
_("Posting Date") + ":Date:100", _("Against Invoice") + ":Link/Purchase Invoice:130",
_("Against Invoice Posting Date") + ":Date:130", _("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
_("Reference No") + "::100", _("Reference Date") + ":Date:100", _("Remarks") + "::150", _("Age") +":Int:40",
@@ -46,41 +47,38 @@ def get_columns():
]
def get_conditions(filters):
conditions = ""
party = None
conditions = []
if filters.get("account"):
party = filters["account"]
else:
conditions += " and company = '%s'" % frappe.db.escape(filters["company"])
if not filters.get("party_type"):
if filters.get("payment_type") == "Outgoing":
filters["party_type"] = "Supplier"
else:
filters["party_type"] = "Customer"
if filters.get("party_type"):
conditions.append("jvd.party_type=%(party_type)s")
account_type = "Receivable" if filters.get("payment_type") == "Incoming" else "Payable"
if filters.get("party"):
conditions.append("jvd.party=%(party)s")
conditions += """ and account in
(select name from tabAccount
where account_type = '{0}'
and company='{1}')""".format(account_type, frappe.db.escape(filters["company"]))
if party:
conditions += " and jvd.party = '%s'" % frappe.db.escape(party)
else:
conditions += " and ifnull(jvd.party, '') != ''"
if filters.get("company"):
conditions.append("jv.company=%(company)s")
if filters.get("from_date"):
conditions += " and jv.posting_date >= '%s'" % filters["from_date"]
conditions.append("jv.posting_date >= %(from_date)s")
if filters.get("to_date"):
conditions += " and jv.posting_date <= '%s'" % filters["to_date"]
conditions.append("jv.posting_date <= %(to_date)s")
return conditions
return "and {}".format(" and ".join(conditions)) if conditions else ""
def get_entries(filters):
conditions = get_conditions(filters)
entries = frappe.db.sql("""select jv.name, jvd.account, jv.posting_date,
entries = frappe.db.sql("""select jv.name, jvd.party_type, jvd.party, jv.posting_date,
jvd.against_voucher, jvd.against_invoice, jvd.debit, jvd.credit,
jv.cheque_no, jv.cheque_date, jv.remark
from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
where jvd.parent = jv.name and jv.docstatus=1 %s order by jv.name DESC""" %
conditions, as_dict=1, debug=1)
conditions, filters, as_dict=1)
return entries

View File

@@ -12,7 +12,6 @@ def execute(filters=None):
invoice_list = get_invoices(filters)
columns, expense_accounts, tax_accounts = get_columns(invoice_list)
if not invoice_list:
msgprint(_("No record found"))
return columns, invoice_list
@@ -30,7 +29,8 @@ def execute(filters=None):
purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])))
project_name = list(set(invoice_po_pr_map.get(inv.name, {}).get("project_name", [])))
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name, supplier_details.get(inv.supplier),
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name,
supplier_details.get(inv.supplier),
inv.credit_to, ", ".join(project_name), inv.bill_no, inv.bill_date, inv.remarks,
", ".join(purchase_order), ", ".join(purchase_receipt)]
@@ -54,8 +54,7 @@ def execute(filters=None):
# total tax, grand total, outstanding amount & rounded total
row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount]
data.append(row)
# raise Exception
data.append(row)
return columns, data
@@ -107,7 +106,7 @@ def get_conditions(filters):
def get_invoices(filters):
conditions = get_conditions(filters)
return frappe.db.sql("""select name, posting_date, credit_to, supplier, supplier_name
return frappe.db.sql("""select name, posting_date, credit_to, supplier, supplier_name,
bill_no, bill_date, remarks, base_net_total, base_grand_total, outstanding_amount
from `tabPurchase Invoice` where docstatus = 1 %s
order by posting_date desc, name desc""" % conditions, filters, as_dict=1)

View File

@@ -30,7 +30,8 @@ def execute(filters=None):
delivery_note = list(set(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", [])))
row = [inv.name, inv.posting_date, inv.customer, inv.customer_name,
customer_map.get(inv.customer)["customer_group"], customer_map.get(inv.customer)["territory"],
customer_map.get(inv.customer, {}).get("customer_group"),
customer_map.get(inv.customer, {}).get("territory"),
inv.debit_to, inv.project_name, inv.remarks, ", ".join(sales_order), ", ".join(delivery_note)]
# map income values

View File

@@ -9,7 +9,7 @@ from erpnext.accounts.report.financial_statements import filter_accounts, get_gl
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
def execute(filters):
def execute(filters=None):
validate_filters(filters)
data = get_data(filters)
columns = get_columns()
@@ -45,8 +45,8 @@ def validate_filters(filters):
filters.to_date = filters.year_end_date
def get_data(filters):
accounts = frappe.db.sql("""select * from `tabAccount` where company=%s order by lft""",
filters.company, as_dict=True)
accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
if not accounts:
return None
@@ -56,17 +56,58 @@ def get_data(filters):
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
where company=%s""", (filters.company,))[0]
gl_entries_by_account = get_gl_entries(filters.company, None, filters.to_date, min_lft, max_rgt,
gl_entries_by_account = get_gl_entries(filters.company, filters.from_date, filters.to_date, min_lft, max_rgt,
ignore_closing_entries=not flt(filters.with_period_closing_entry))
total_row = calculate_values(accounts, gl_entries_by_account, filters)
opening_balances = get_opening_balances(filters)
total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters)
accumulate_values_into_parents(accounts, accounts_by_name)
data = prepare_data(accounts, filters, total_row)
return data
def get_opening_balances(filters):
balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet")
pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss")
balance_sheet_opening.update(pl_opening)
return balance_sheet_opening
def get_rootwise_opening_balances(filters, report_type):
additional_conditions = " and posting_date >= %(year_start_date)s" \
if report_type == "Profit and Loss" else ""
if not flt(filters.with_period_closing_entry):
additional_conditions += " and ifnull(voucher_type, '')!='Period Closing Voucher'"
gle = frappe.db.sql("""
select
account, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
from `tabGL Entry`
where
company=%(company)s
{additional_conditions}
and posting_date < %(from_date)s
and account in (select name from `tabAccount` where report_type=%(report_type)s)
group by account""".format(additional_conditions=additional_conditions),
{
"company": filters.company,
"from_date": filters.from_date,
"report_type": report_type,
"year_start_date": filters.year_start_date
},
as_dict=True)
opening = frappe._dict()
for d in gle:
opening.setdefault(d.account, d)
return opening
def calculate_values(accounts, gl_entries_by_account, filters):
def calculate_values(accounts, gl_entries_by_account, opening_balances, filters):
init = {
"opening_debit": 0.0,
"opening_credit": 0.0,
@@ -88,29 +129,15 @@ def calculate_values(accounts, gl_entries_by_account, filters):
d.update(init.copy())
for entry in gl_entries_by_account.get(d.name, []):
posting_date = getdate(entry.posting_date)
# opening
if posting_date < filters.from_date:
is_valid_opening = (d.root_type in ("Asset", "Liability", "Equity") or
(filters.year_start_date <= posting_date < filters.from_date))
if is_valid_opening:
d["opening_debit"] += flt(entry.debit)
d["opening_credit"] += flt(entry.credit)
elif posting_date <= filters.to_date:
if entry.is_opening == "Yes" and d.root_type in ("Asset", "Liability", "Equity"):
d["opening_debit"] += flt(entry.debit)
d["opening_credit"] += flt(entry.credit)
else:
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
total_row["debit"] += d["debit"]
total_row["credit"] += d["credit"]
# add opening
d["opening_debit"] = opening_balances.get(d.name, {}).get("opening_debit", 0)
d["opening_credit"] = opening_balances.get(d.name, {}).get("opening_credit", 0)
return total_row

View File

@@ -91,7 +91,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
# different filter for group and ledger - improved performance
if acc.is_group:
cond.append("""exists (
select * from `tabAccount` ac where ac.name = gle.account
select name from `tabAccount` ac where ac.name = gle.account
and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt))
else:
@@ -397,7 +397,7 @@ def get_outstanding_invoices(amount_query, account, party_type, party):
for d in outstanding_voucher_list:
payment_amount = frappe.db.sql("""
select ifnull(sum(ifnull({amount_query}, 0)), 0)
select ifnull(sum({amount_query}), 0)
from
`tabGL Entry`
where

View File

@@ -26,7 +26,7 @@
"reqd": 1
},
{
"description": "Supplier (vendor) name as entered in supplier master",
"description": "",
"fieldname": "supplier",
"fieldtype": "Link",
"in_filter": 1,
@@ -873,7 +873,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:02.452899",
"modified": "2015-06-02 17:15:44.711032",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -75,7 +75,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -538,7 +538,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:16.553472",
"modified": "2015-06-02 14:19:21.459032",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -57,3 +57,7 @@ cur_frm.fields_dict['item_serial_no'].get_query = function(doc, cdt, cdn) {
return { filters: filter }
}
cur_frm.add_fetch('item_code', 'item_name', 'item_name');
cur_frm.add_fetch('item_code', 'description', 'description');

View File

@@ -127,6 +127,14 @@
"permlevel": 0,
"width": "50%"
},
{
"fieldname": "item_name",
"fieldtype": "Data",
"label": "Item Name",
"permlevel": 0,
"precision": "",
"read_only": 1
},
{
"fieldname": "description",
"fieldtype": "Small Text",
@@ -219,7 +227,7 @@
"icon": "icon-search",
"idx": 1,
"is_submittable": 1,
"modified": "2015-04-14 07:37:07.331291",
"modified": "2015-06-08 02:40:25.121948",
"modified_by": "Administrator",
"module": "Buying",
"name": "Quality Inspection",

View File

@@ -31,7 +31,6 @@ class QualityInspection(Document):
(self.name, self.modified, self.purchase_receipt_no,
self.item_code))
def on_cancel(self):
if self.purchase_receipt_no:
frappe.db.sql("""update `tabPurchase Receipt Item` t1, `tabPurchase Receipt` t2
@@ -39,7 +38,6 @@ class QualityInspection(Document):
where t1.parent = %s and t1.item_code = %s and t1.parent = t2.name""",
(self.modified, self.purchase_receipt_no, self.item_code))
def item_query(doctype, txt, searchfield, start, page_len, filters):
if filters.get("from"):
from frappe.desk.reportview import get_match_cond

View File

@@ -26,7 +26,7 @@
"reqd": 1
},
{
"description": "Supplier (vendor) name as entered in supplier master",
"description": "",
"fieldname": "supplier",
"fieldtype": "Link",
"in_filter": 1,
@@ -660,7 +660,7 @@
"icon": "icon-shopping-cart",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:02.098540",
"modified": "2015-06-02 17:15:57.283516",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

@@ -59,7 +59,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -413,7 +413,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.853886",
"modified": "2015-06-02 14:19:33.922968",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",

View File

@@ -0,0 +1,2 @@
- Introduced `Round Off` account to book rounding loss automatically
- Added 2 new fields 'Round Off Account' and 'Round Off Cost Center' in Company

View File

@@ -31,7 +31,7 @@ def get_data():
{
"type": "help",
"label": _("Opening Stock Balance"),
"youtube_id": "yPgrtfeCTs"
"youtube_id": "0yPgrtfeCTs"
},
{
"type": "help",
@@ -106,7 +106,7 @@ def get_data():
{
"type": "help",
"label": _("Opening Stock Balance"),
"youtube_id": "yPgrtfeCTs"
"youtube_id": "0yPgrtfeCTs"
},
{
"type": "help",

View File

@@ -266,7 +266,7 @@ def get_data():
{
"type": "help",
"label": _("Opening Stock Balance"),
"youtube_id": "yPgrtfeCTs"
"youtube_id": "0yPgrtfeCTs"
},
{
"type": "help",

View File

@@ -38,7 +38,8 @@ class AccountsController(TransactionBase):
convert_to_recurring(self, self.get("posting_date") or self.get("transaction_date"))
def before_recurring(self):
self.fiscal_year = None
if self.meta.get_field("fiscal_year"):
self.fiscal_year = None
if self.meta.get_field("due_date"):
self.due_date = None
@@ -46,7 +47,7 @@ class AccountsController(TransactionBase):
for fieldname in ["posting_date", "transaction_date"]:
if not self.get(fieldname) and self.meta.get_field(fieldname):
self.set(fieldname, today())
if not self.fiscal_year:
if self.meta.get_field("fiscal_year") and not self.fiscal_year:
self.fiscal_year = get_fiscal_year(self.get(fieldname))[0]
break
@@ -334,7 +335,7 @@ class AccountsController(TransactionBase):
@frappe.whitelist()
def get_tax_rate(account_head):
return frappe.db.get_value("Account", account_head, "tax_rate")
@frappe.whitelist()
def get_default_taxes_and_charges(master_doctype):
default_tax = frappe.db.get_value(master_doctype, {"is_default": 1})

View File

@@ -78,7 +78,7 @@ class StatusUpdater(Document):
self.status = s[0]
break
if self.status != _status:
if self.status != _status and self.status not in ("Submitted", "Cancelled"):
self.add_comment("Label", _(self.status))
if update:

View File

@@ -44,11 +44,14 @@ class NewsletterList(Document):
return self.update_total_subscribers()
def update_total_subscribers(self):
self.total_subscribers = frappe.db.sql("""select count(*) from `tabNewsletter List Subscriber`
where newsletter_list=%s""", self.name)[0][0]
self.total_subscribers = self.get_total_subscribers()
self.db_update()
return self.total_subscribers
def get_total_subscribers(self):
return frappe.db.sql("""select count(*) from `tabNewsletter List Subscriber`
where newsletter_list=%s""", self.name)[0][0]
def on_trash(self):
for d in frappe.get_all("Newsletter List Subscriber", "name", {"newsletter_list": self.name}):
frappe.delete_doc("Newsletter List Subscriber", d.name)

View File

@@ -85,7 +85,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -134,7 +134,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-14 14:55:18.325286",
"modified": "2015-06-02 14:18:16.622288",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity Item",

View File

@@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors"
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
app_icon = "icon-th"
app_color = "#e74c3c"
app_version = "5.0.12"
app_version = "5.0.24"
error_report_email = "support@erpnext.com"
@@ -38,16 +38,14 @@ website_route_rules = [
{"from_route": "/invoices", "to_route": "Sales Invoice"},
{"from_route": "/invoices/<path:name>", "to_route": "print", "defaults": {"doctype": "Sales Invoice"}},
{"from_route": "/shipments", "to_route": "Delivery Note"},
{"from_route": "/shipments/<path:name>", "to_route": "print", "defaults": {"doctype": "Delivery Note"}},
{"from_route": "/issues", "to_route": "Issue"},
{"from_route": "/issues/<path:name>", "to_route": "print", "defaults": {"doctype": "Issue"}},
{"from_route": "/addresses", "to_route": "Address"},
{"from_route": "/shipments/<path:name>", "to_route": "print", "defaults": {"doctype": "Delivery Note"}}
]
has_website_permission = {
"Sales Order": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Sales Invoice": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission"
"Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission",
"Issue": "erpnext.support.doctype.issue.issue.has_website_permission"
}
dump_report_map = "erpnext.startup.report_data_map.data_map"

View File

@@ -23,9 +23,6 @@ class LeaveAllocation(Document):
def on_update(self):
self.get_total_allocated_leaves()
def on_cancel(self):
self.check_for_leave_application()
def validate_new_leaves_allocated_value(self):
"""validate that leave allocation is in multiples of 0.5"""
if flt(self.new_leaves_allocated) % 0.5:

View File

@@ -130,6 +130,7 @@
"description": "",
"fieldname": "leave_approver",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Leave Approver",
"options": "User",
"permlevel": 0
@@ -216,7 +217,7 @@
"idx": 1,
"is_submittable": 1,
"max_attachments": 3,
"modified": "2015-04-30 02:19:39.330689",
"modified": "2015-05-27 18:44:36.708614",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Application",

View File

@@ -24,4 +24,8 @@ cur_frm.cscript.to_date = function(doc, cdt, cdn) {
cur_frm.cscript.allocation_type = function (doc, cdt, cdn){
doc.no_of_days = '';
refresh_field('no_of_days');
}
}
frappe.ui.form.on("Leave Control Panel", "refresh", function(frm) {
frm.disable_save();
});

View File

@@ -94,11 +94,11 @@
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"hide_toolbar": 1,
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:40.791976",
"modified": "2015-06-05 11:38:19.994852",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Control Panel",
@@ -110,7 +110,7 @@
"read": 1,
"report": 0,
"role": "HR User",
"share": 1,
"share": 0,
"submit": 0,
"write": 1
}

View File

@@ -43,3 +43,8 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
frappe.set_route("Form", doc.doctype, doc.name);
});
}
frappe.ui.form.on("Salary Manager", "refresh", function(frm) {
frm.disable_save();
});

View File

@@ -150,10 +150,11 @@
"permlevel": 0
}
],
"hide_toolbar": 1,
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-25 07:21:04.778082",
"modified": "2015-06-05 11:33:00.152362",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Manager",

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt
from frappe.utils import cstr, flt, getdate
from frappe.model.naming import make_autoname
from frappe import _
from frappe.model.mapper import get_mapped_doc
@@ -14,6 +14,13 @@ from erpnext.hr.utils import set_employee_name
class SalaryStructure(Document):
def autoname(self):
self.name = make_autoname(self.employee + '/.SST' + '/.#####')
def validate(self):
self.check_existing()
self.validate_amount()
self.validate_employee()
self.validate_joining_date()
set_employee_name(self)
def get_employee_details(self):
ret = {}
@@ -77,14 +84,11 @@ class SalaryStructure(Document):
old_employee = frappe.db.get_value("Salary Structure", self.name, "employee")
if old_employee and self.employee != old_employee:
frappe.throw(_("Employee can not be changed"))
def validate(self):
self.check_existing()
self.validate_amount()
self.validate_employee()
set_employee_name(self)
def validate_joining_date(self):
joining_date = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining"))
if getdate(self.from_date) < joining_date:
frappe.throw(_("From Date in Salary Structure cannot be lesser than Employee Joining Date."))
@frappe.whitelist()
def make_salary_slip(source_name, target_doc=None):

View File

@@ -12,6 +12,7 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
},
refresh: function() {
this.frm.disable_save();
this.show_upload();
},

View File

@@ -1,4 +1,5 @@
{
"allow_copy": 1,
"creation": "2013-01-25 11:34:53",
"docstatus": 0,
"doctype": "DocType",
@@ -53,11 +54,13 @@
"permlevel": 0
}
],
"hide_heading": 0,
"hide_toolbar": 1,
"icon": "icon-upload-alt",
"idx": 1,
"issingle": 1,
"max_attachments": 1,
"modified": "2015-02-05 05:11:48.540845",
"modified": "2015-06-05 11:37:04.348120",
"modified_by": "Administrator",
"module": "HR",
"name": "Upload Attendance",
@@ -65,25 +68,25 @@
"permissions": [
{
"create": 1,
"email": 1,
"email": 0,
"permlevel": 0,
"print": 1,
"print": 0,
"read": 1,
"report": 0,
"role": "HR User",
"share": 1,
"share": 0,
"submit": 0,
"write": 1
},
{
"create": 1,
"email": 1,
"email": 0,
"permlevel": 0,
"print": 1,
"print": 0,
"read": 1,
"report": 0,
"role": "HR Manager",
"share": 1,
"share": 0,
"submit": 0,
"write": 1
}

View File

@@ -424,6 +424,6 @@ def validate_bom_no(item, bom_no):
if bom.docstatus != 1:
if not getattr(frappe.flags, "in_test", False):
frappe.throw(_("BOM {0} must be submitted").format(bom_no))
if item and not (bom.item == item or \
bom.item == frappe.db.get_value("Item", item, "variant_of")):
if item and not (bom.item.lower() == item.lower() or \
bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower()):
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))

View File

@@ -217,12 +217,14 @@ class ProductionOrder(Document):
for i, d in enumerate(self.operations):
self.set_operation_start_end_time(i, d)
if not d.workstation:
continue
time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time,
flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name)
if d.workstation:
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
original_start_time = time_log.from_time
while True:
@@ -309,10 +311,9 @@ class ProductionOrder(Document):
self.actual_end_date = None
def validate_delivery_date(self):
if self.docstatus==1:
if self.planned_end_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_end_date):
frappe.msgprint(_("Production might not be able to finish by the Expected Delivery Date."))
if self.planned_start_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_start_date):
frappe.throw(_("Expected Delivery Date must be greater than Planned Start Date."))
def delete_time_logs(self):
for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):

View File

@@ -1,4 +1,5 @@
{
"allow_copy": 1,
"creation": "2013-01-21 12:03:47",
"default_print_format": "Standard",
"docstatus": 0,
@@ -154,11 +155,12 @@
"permlevel": 0
}
],
"hide_toolbar": 1,
"icon": "icon-calendar",
"idx": 1,
"in_create": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:43.010625",
"modified": "2015-06-05 11:44:31.629114",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Planning Tool",

View File

@@ -161,3 +161,9 @@ erpnext.patches.v5_0.set_footer_address
execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0)
execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'")
erpnext.patches.v5_0.update_item_and_description_again
erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
erpnext.patches.v5_0.portal_fixes
erpnext.patches.v5_0.reset_values_in_tools
execute:frappe.delete_doc("Page", "users")
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
erpnext.patches.v5_0.index_on_account_and_gl_entry

View File

@@ -0,0 +1,22 @@
from __future__ import unicode_literals
import frappe
def execute():
index_map = {
"Account": ["parent_account", "lft", "rgt"],
"GL Entry": ["posting_date", "account", 'party', "voucher_no"]
}
for dt, indexes in index_map.items():
existing_indexes = [d.Key_name for d in frappe.db.sql("""show index from `tab{0}`
where Column_name != 'name'""".format(dt), as_dict=1)]
for old in existing_indexes:
if old in ("parent", "group_or_ledger", "is_pl_account", "debit_or_credit", "account_name", "company"):
frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old))
existing_indexes.remove(old)
for new in indexes:
if new not in existing_indexes:
frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new))

View File

@@ -0,0 +1,6 @@
import frappe
import erpnext.setup.install
def execute():
frappe.reload_doc("website", "doctype", "web_form_field", force=True)
erpnext.setup.install.add_web_forms()

View File

@@ -9,13 +9,13 @@ def execute():
# NOTE: sequence is important
renamed_fields = get_all_renamed_fields()
for dt, script_field in (("Custom Script", "script"), ("Print Format", "html")):
for dt, script_field, ref_dt_field in (("Custom Script", "script", "dt"), ("Print Format", "html", "doc_type")):
cond1 = " or ".join("""{0} like "%%{1}%%" """.format(script_field, d[0].replace("_", "\\_")) for d in renamed_fields)
cond2 = " and standard = 'No'" if dt == "Print Format" else ""
for name, script in frappe.db.sql("select name, {0} as script from `tab{1}` where ({2}) {3}".format(script_field, dt, cond1, cond2)):
update_script(dt, name, script_field, script, renamed_fields)
for name, script, ref_dt in frappe.db.sql("select name, {0} as script, {1} as ref_dt from `tab{2}` where ({3}) {4}".format(script_field, ref_dt_field, dt, cond1, cond2)):
update_script(dt, name, ref_dt, script_field, script, renamed_fields)
def get_all_renamed_fields():
from erpnext.patches.v5_0.rename_table_fieldnames import rename_map
@@ -46,20 +46,20 @@ def get_all_renamed_fields():
)
for fields in rename_map.values():
valid_fields = [d for d in fields if d[0] != "entries"]
renamed_fields += tuple(valid_fields)
renamed_fields += tuple(fields)
return renamed_fields
def update_script(dt, name, script_field, script, renamed_fields):
def update_script(dt, name, ref_dt, script_field, script, renamed_fields):
for from_field, to_field in renamed_fields:
script = re.sub(r"\b{}\b".format(from_field), to_field, script)
if dt == "Journal Entry":
if from_field != "entries":
script = re.sub(r"\b{}\b".format(from_field), to_field, script)
if ref_dt == "Journal Entry":
script = re.sub(r"\bentries\b", "accounts", script)
elif dt == "Bank Reconciliation":
elif ref_dt == "Bank Reconciliation":
script = re.sub(r"\bentries\b", "journal_entries", script)
elif dt in ("Sales Invoice", "Purchase Invoice"):
elif ref_dt in ("Sales Invoice", "Purchase Invoice"):
script = re.sub(r"\bentries\b", "items", script)
frappe.db.set_value(dt, name, script_field, script)

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
je_list = frappe.db.sql_list("""
select par.name from `tabJournal Entry` par
where par.docstatus=1 and par.creation > '2015-03-01'
and (select count(distinct child.party) from `tabJournal Entry Account` child
where par.name=child.parent and ifnull(child.party, '') != '') > 1
""")
for d in je_list:
# delete existing gle
frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
# repost gl entries
je = frappe.get_doc("Journal Entry", d)
je.make_gl_entries()
if je_list:
print je_list

View File

@@ -0,0 +1,11 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
for dt in ["Payment Tool", "Bank Reconciliation", "Payment Reconciliation", "Leave Control Panel",
"Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Replace Tool"]:
frappe.db.sql("delete from `tabSingles` where doctype=%s", dt)

View File

@@ -0,0 +1,18 @@
import frappe
def execute():
pro_order_qty_transferred = frappe._dict()
for se in frappe.db.sql("""select production_order, sum(fg_completed_qty) as transferred_qty
from `tabStock Entry`
where docstatus=1 and ifnull(production_order, '') != ''
and purpose = 'Material Transfer for Manufacture'
group by production_order""", as_dict=1):
pro_order_qty_transferred.setdefault(se.production_order, se.transferred_qty)
for d in frappe.get_all("Production Order", filters={"docstatus": 1}, fields=["name", "qty"]):
if d.name in pro_order_qty_transferred:
material_transferred_for_manufacturing = pro_order_qty_transferred.get(d.name) \
if pro_order_qty_transferred.get(d.name) <= d.qty else d.qty
frappe.db.sql("""update `tabProduction Order` set material_transferred_for_manufacturing=%s
where name=%s""", (material_transferred_for_manufacturing, d.name))

View File

@@ -0,0 +1 @@
cur_frm.add_fetch('employee', 'employee_name', 'employee_name');

View File

@@ -2,7 +2,7 @@
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "Activity Cost - .#",
"autoname": "AC-.#####",
"creation": "2015-03-23 02:00:21.861546",
"custom": 0,
"docstatus": 0,
@@ -31,11 +31,12 @@
},
{
"fieldname": "employee_name",
"fieldtype": "Read Only",
"fieldtype": "Data",
"label": "Employee Name",
"options": "employee.employee_name",
"options": "",
"permlevel": 0,
"precision": ""
"precision": "",
"read_only": 1
},
{
"fieldname": "column_break_2",
@@ -135,7 +136,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-04-14 02:08:33.690406",
"modified": "2015-06-11 06:50:47.999788",
"modified_by": "Administrator",
"module": "Projects",
"name": "Activity Cost",

View File

@@ -15,6 +15,8 @@ class ActivityCost(Document):
self.check_unique()
def set_title(self):
if not self.employee_name:
self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
def check_unique(self):

View File

@@ -163,6 +163,7 @@
"fieldtype": "Percent",
"in_list_view": 0,
"label": "% Tasks Completed",
"no_copy": 1,
"permlevel": 0,
"read_only": 1
},
@@ -356,7 +357,7 @@
"icon": "icon-puzzle-piece",
"idx": 1,
"max_attachments": 4,
"modified": "2015-04-27 07:37:44.239930",
"modified": "2015-06-12 09:00:54.080220",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",

View File

@@ -15,16 +15,23 @@ class Project(Document):
def onload(self):
"""Load project tasks for quick view"""
for task in frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc"):
self.append("tasks", {
"title": task.subject,
"status": task.status,
"start_date": task.exp_start_date,
"end_date": task.exp_end_date,
"description": task.description,
"task_id": task.name
})
if not self.get("tasks"):
for task in self.get_tasks():
self.append("tasks", {
"title": task.subject,
"status": task.status,
"start_date": task.exp_start_date,
"end_date": task.exp_end_date,
"description": task.description,
"task_id": task.name
})
def __setup__(self):
self.onload()
def get_tasks(self):
return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc")
def validate(self):
self.validate_dates()
self.sync_tasks()

View File

@@ -28,7 +28,11 @@ class Task(Document):
def validate(self):
self.validate_dates()
if self.status!=self.get_db_value("status") and self.status == "Closed":
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
def validate_dates(self):
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'"))
@@ -41,17 +45,17 @@ class Task(Document):
self.reschedule_dependent_tasks()
self.update_percentage()
self.update_project()
def update_percentage(self):
"""update percent complete in project"""
if self.project and not self.flags.from_project:
project = frappe.get_doc("Project", self.project)
project.run_method("update_percent_complete")
def update_total_expense_claim(self):
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.name))
def update_time_and_costing(self):
tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
@@ -64,14 +68,14 @@ class Task(Document):
self.actual_time= tl.time
self.act_start_date= tl.start_date
self.act_end_date= tl.end_date
def update_project(self):
if self.project and frappe.db.exists("Project", self.project):
project = frappe.get_doc("Project", self.project)
project.flags.dont_sync_tasks = True
project.update_costing()
project.save()
def check_recursion(self):
if self.flags.ignore_recursion_check: return
check_list = [['task', 'parent'], ['parent', 'task']]
@@ -88,7 +92,7 @@ class Task(Document):
task_list.append(b[0])
if count == 15:
break
def reschedule_dependent_tasks(self):
end_date = self.exp_end_date or self.act_end_date
if end_date:

View File

@@ -11,19 +11,19 @@ from erpnext.projects.doctype.task.task import CircularReferenceError
class TestTask(unittest.TestCase):
def test_circular_reference(self):
task1 = frappe.new_doc('Task')
task1.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -34,10 +34,10 @@ class TestTask(unittest.TestCase):
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -53,13 +53,13 @@ class TestTask(unittest.TestCase):
"task": task3.name
})
self.assertRaises(CircularReferenceError, task1.save)
task1.set("depends_on", [])
task1.save()
task4 = frappe.new_doc('Task')
task4.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-15",
@@ -74,20 +74,20 @@ class TestTask(unittest.TestCase):
task3.append("depends_on", {
"task": task4.name
})
def test_reschedule_dependent_task(self):
task1 = frappe.new_doc('Task')
task1.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -98,10 +98,10 @@ class TestTask(unittest.TestCase):
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 3",
"exp_start_date": "2015-1-16",
"exp_end_date": "2015-1-18",
@@ -112,18 +112,18 @@ class TestTask(unittest.TestCase):
]
})
task3.save()
task1.update({
"exp_end_date": "2015-1-20"
})
task1.save()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
time_log = frappe.new_doc('Time Log')
time_log.update({
"from_time": "2015-1-1",
@@ -131,18 +131,49 @@ class TestTask(unittest.TestCase):
"task": task1.name
})
time_log.submit()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
time_log.cancel()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
def test_close_assignment(self):
task = frappe.new_doc("Task")
task.subject = "Test Close Assignment"
task.insert()
def assign():
from frappe.desk.form import assign_to
assign_to.add({
"assign_to": "test@example.com",
"doctype": task.doctype,
"name": task.name,
"description": "Close this task"
})
def get_owner_and_status():
return frappe.db.get_value("ToDo", filters={"reference_type": task.doctype, "reference_name": task.name,
"description": "Close this task"}, fieldname=("owner", "status"), as_dict=True)
assign()
todo = get_owner_and_status()
self.assertEquals(todo.owner, "test@example.com")
self.assertEquals(todo.status, "Open")
# assignment should be
task.load_from_db()
task.status = "Closed"
task.save()
todo = get_owner_and_status()
self.assertEquals(todo.owner, "test@example.com")
self.assertEquals(todo.status, "Closed")

View File

@@ -128,7 +128,7 @@ class TimeLog(Document):
def update_production_order(self):
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
if self.production_order and self.for_manufacturing:
if not self.operation_id:
frappe.throw(_("Operation ID not set"))
@@ -195,8 +195,6 @@ class TimeLog(Document):
if self.for_manufacturing:
if not self.production_order:
frappe.throw(_("Production Order is Mandatory"))
if not self.operation:
frappe.throw(_("Operation is Mandatory"))
if not self.completed_qty:
self.completed_qty = 0
@@ -210,22 +208,23 @@ class TimeLog(Document):
self.production_order = None
self.operation = None
self.quantity = None
def update_cost(self):
rate = get_activity_cost(self.employee, self.activity_type)
if rate:
self.costing_rate = rate.get('costing_rate')
self.billing_rate = rate.get('billing_rate')
self.billing_rate = rate.get('billing_rate')
self.costing_amount = self.costing_rate * self.hours
if self.billable:
self.billing_amount = self.billing_rate * self.hours
else:
self.billing_amount = 0
def validate_task(self):
if self.project and not self.task:
# if a time log is being created against a project without production order
if (self.project and not self.production_order) and not self.task:
frappe.throw(_("Task is Mandatory if Time Log is against a project"))
def update_task(self):
if self.task and frappe.db.exists("Task", self.task):
task = frappe.get_doc("Task", self.task)
@@ -268,7 +267,7 @@ def get_events(start, end, filters=None):
d.title += " for Project: " + d.project
return data
@frappe.whitelist()
def get_activity_cost(employee=None, activity_type=None):
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where employee= %s

View File

@@ -105,6 +105,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
barcode: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.barcode=="" || d.barcode==null) {
// barcode cleared, remove item
d.item_code = "";
}
this.item_code(doc, cdt, cdn);
},
item_code: function(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);

View File

@@ -81,7 +81,8 @@ erpnext.feature_setup.feature_dict = {
'Item': {'fields': ['barcode']},
'Delivery Note': {'items': ['barcode']},
'Sales Invoice': {'items': ['barcode']},
'Stock Entry': {'items': ['barcode']}
'Stock Entry': {'items': ['barcode']},
'Purchase Receipt': {'items': ['barcode']}
},
'fs_item_group_in_details': {
'Delivery Note': {'items':['item_group']},

View File

@@ -139,7 +139,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
if(sl.voucher_type=="Stock Reconciliation") {
var diff = (sl.qty_after_transaction * sl.valuation_rate) - item.closing_qty_value;
wh.fifo_stack.push([sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]);
wh.fifo_stack = [[sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]];
wh.balance_qty = sl.qty_after_transaction;
wh.balance_value = sl.valuation_rate * sl.qty_after_transaction;
} else {
@@ -167,7 +167,6 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
},
update_groups: function() {
var me = this;
$.each(this.data, function(i, item) {
// update groups
if(!item.is_group && me.apply_filter(item, "brand")) {

View File

@@ -55,7 +55,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -298,12 +298,13 @@
},
{
"fieldname": "prevdoc_doctype",
"fieldtype": "Data",
"fieldtype": "Link",
"hidden": 1,
"label": "Against Doctype",
"no_copy": 1,
"oldfieldname": "prevdoc_doctype",
"oldfieldtype": "Data",
"options": "DocType",
"permlevel": 0,
"print_hide": 1,
"print_width": "150px",
@@ -313,11 +314,12 @@
},
{
"fieldname": "prevdoc_docname",
"fieldtype": "Data",
"fieldtype": "Dynamic Link",
"label": "Against Docname",
"no_copy": 1,
"oldfieldname": "prevdoc_docname",
"oldfieldtype": "Data",
"options": "prevdoc_doctype",
"permlevel": 0,
"print_hide": 1,
"print_width": "150px",
@@ -390,7 +392,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:15.474119",
"modified": "2015-06-02 14:18:00.266748",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",

View File

@@ -8,6 +8,13 @@ frappe.query_reports["Customers Not Buying Since Long Time"] = {
"label": __("Days Since Last Order"),
"fieldtype": "Int",
"default": 60
},
{
"fieldname":"doctype",
"label": __("Doctype"),
"fieldtype": "Select",
"default": "Sales Order",
"options": "Sales Order\nSales Invoice"
}
]
}

View File

@@ -10,41 +10,51 @@ def execute(filters=None):
if not filters: filters ={}
days_since_last_order = filters.get("days_since_last_order")
doctype = filters.get("doctype")
if cint(days_since_last_order) <= 0:
frappe.throw(_("'Days Since Last Order' must be greater than or equal to zero"))
columns = get_columns()
customers = get_so_details()
customers = get_sales_details(doctype)
data = []
for cust in customers:
if cint(cust[8]) >= cint(days_since_last_order):
cust.insert(7,get_last_so_amt(cust[0]))
cust.insert(7,get_last_sales_amt(cust[0], doctype))
data.append(cust)
return columns, data
def get_so_details():
def get_sales_details(doctype):
cond = """sum(so.base_net_total) as 'total_order_considered',
max(so.posting_date) as 'last_order_date',
DATEDIFF(CURDATE(), max(so.posting_date)) as 'days_since_last_order' """
if doctype == "Sales Order":
cond = """sum(if(so.status = "Stopped",
so.base_net_total * so.per_delivered/100,
so.base_net_total)) as 'total_order_considered',
max(so.transaction_date) as 'last_order_date',
DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order'"""
return frappe.db.sql("""select
cust.name,
cust.customer_name,
cust.territory,
cust.customer_group,
count(distinct(so.name)) as 'num_of_order',
sum(base_net_total) as 'total_order_value',
sum(if(so.status = "Stopped",
so.base_net_total * so.per_delivered/100,
so.base_net_total)) as 'total_order_considered',
max(so.transaction_date) as 'last_sales_order_date',
DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order'
from `tabCustomer` cust, `tabSales Order` so
sum(base_net_total) as 'total_order_value', {0}
from `tabCustomer` cust, `tab{1}` so
where cust.name = so.customer and so.docstatus = 1
group by cust.name
order by 'days_since_last_order' desc """,as_list=1)
order by 'days_since_last_order' desc """.format(cond, doctype), as_list=1)
def get_last_so_amt(customer):
res = frappe.db.sql("""select base_net_total from `tabSales Order`
where customer ='%(customer)s' and docstatus = 1 order by transaction_date desc
limit 1""" % {'customer': frappe.db.escape(customer)})
def get_last_sales_amt(customer, doctype):
cond = "posting_date"
if doctype =="Sales Order":
cond = "transaction_date"
res = frappe.db.sql("""select base_net_total from `tab{0}`
where customer = %s and docstatus = 1 order by {1} desc
limit 1""".format(doctype, cond), customer)
return res and res[0][0] or 0
@@ -58,6 +68,6 @@ def get_columns():
_("Total Order Value") + ":Currency:120",
_("Total Order Considered") + ":Currency:160",
_("Last Order Amount") + ":Currency:160",
_("Last Sales Order Date") + ":Date:160",
_("Last Order Date") + ":Date:160",
_("Days Since Last Order") + "::160"
]

View File

@@ -124,15 +124,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
this.apply_pricing_rule();
},
barcode: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.barcode=="" || d.barcode==null) {
// barcode cleared, remove item
d.item_code = "";
}
this.item_code(doc, cdt, cdn);
},
selling_price_list: function() {
this.apply_price_list();
},

View File

@@ -4,6 +4,10 @@
frappe.provide("erpnext.company");
frappe.ui.form.on("Company", {
onload: function(frm) {
erpnext.company.setup_queries(frm);
},
onload_post_render: function(frm) {
frm.get_field("delete_company_transactions").$input.addClass("btn-danger");
},
@@ -114,98 +118,43 @@ cur_frm.cscript.change_abbr = function() {
dialog.show();
}
cur_frm.fields_dict.default_bank_account.get_query = function(doc) {
return{
filters: [
['Account', 'account_type', '=', 'Bank'],
['Account', 'is_group', '=', 0],
['Account', 'company', '=', doc.name]
]
erpnext.company.setup_queries = function(frm) {
$.each([
["default_bank_account", {"account_type": "Bank"}],
["default_cash_account", {"account_type": "Cash"}],
["default_receivable_account", {"account_type": "Receivable"}],
["default_payable_account", {"account_type": "Payable"}],
["default_expense_account", {"root_type": "Expense"}],
["default_income_account", {"root_type": "Income"}],
["round_off_account", {"root_type": "Expense"}],
["cost_center", {}],
["round_off_cost_center", {}]
], function(i, v) {
erpnext.company.set_custom_query(frm, v);
});
if (sys_defaults.auto_accounting_for_stock) {
$.each([
["stock_adjustment_account", {"root_type": "Expense"}],
["expenses_included_in_valuation", {"root_type": "Expense"}],
["stock_received_but_not_billed", {"report_type": "Balance Sheet"}]
], function(i, v) {
erpnext.company.set_custom_query(frm, v);
});
}
}
cur_frm.fields_dict.default_cash_account.get_query = function(doc) {
return{
filters: [
['Account', 'account_type', '=', 'Cash'],
['Account', 'is_group', '=', 0],
['Account', 'company', '=', doc.name]
]
}
}
erpnext.company.set_custom_query = function(frm, v) {
var filters = {
"company": frm.doc.name,
"is_group": 0
};
for (var key in v[1])
filters[key] = v[1][key];
cur_frm.fields_dict.default_receivable_account.get_query = function(doc) {
return{
filters:{
'company': doc.name,
"is_group": 0,
"account_type": "Receivable"
}
}
}
cur_frm.fields_dict.default_payable_account.get_query = function(doc) {
return{
filters:{
'company': doc.name,
"is_group": 0,
"account_type": "Payable"
}
}
}
cur_frm.fields_dict.default_expense_account.get_query = function(doc) {
return{
filters:{
'company': doc.name,
"is_group": 0,
"report_type": "Profit and Loss"
}
}
}
cur_frm.fields_dict.default_income_account.get_query = function(doc) {
return{
filters:{
'company': doc.name,
"is_group": 0,
"report_type": "Profit and Loss"
}
}
}
cur_frm.fields_dict.cost_center.get_query = function(doc) {
return{
filters:{
'company': doc.name,
"is_group": 0,
}
}
}
if (sys_defaults.auto_accounting_for_stock) {
cur_frm.fields_dict["stock_adjustment_account"].get_query = function(doc) {
frm.set_query(v[0], function() {
return {
"filters": {
"report_type": "Profit and Loss",
"company": doc.name,
"is_group": 0
}
}
}
cur_frm.fields_dict["expenses_included_in_valuation"].get_query =
cur_frm.fields_dict["stock_adjustment_account"].get_query;
cur_frm.fields_dict["stock_received_but_not_billed"].get_query = function(doc) {
return {
"filters": {
"report_type": "Balance Sheet",
"company": doc.name,
"is_group": 0
}
}
}
}
filters: filters
};
});
}

View File

@@ -170,6 +170,15 @@
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "round_off_account",
"fieldtype": "Link",
"ignore_user_permissions": 0,
"label": "Round Off Account",
"options": "Account",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
@@ -211,6 +220,15 @@
"options": "Account",
"permlevel": 0
},
{
"fieldname": "round_off_cost_center",
"fieldtype": "Link",
"ignore_user_permissions": 0,
"label": "Round Off Cost Center",
"options": "Cost Center",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_22",
"fieldtype": "Section Break",
@@ -414,7 +432,7 @@
],
"icon": "icon-building",
"idx": 1,
"modified": "2015-05-19 02:00:41.055138",
"modified": "2015-05-28 12:56:18.175509",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",

View File

@@ -114,6 +114,7 @@ class Company(Document):
def set_default_accounts(self):
self._set_default_account("default_cash_account", "Cash")
self._set_default_account("default_bank_account", "Bank")
self._set_default_account("round_off_account", "Round Off")
if cint(frappe.db.get_single_value("Accounts Settings", "auto_accounting_for_stock")):
self._set_default_account("stock_received_but_not_billed", "Stock Received But Not Billed")
@@ -161,6 +162,7 @@ class Company(Document):
cc_doc.insert()
frappe.db.set(self, "cost_center", _("Main") + " - " + self.abbr)
frappe.db.set(self, "round_off_cost_center", _("Main") + " - " + self.abbr)
def before_rename(self, olddn, newdn, merge=False):
if merge:

View File

@@ -27,12 +27,7 @@ def delete_for_doctype(doctype, company_name):
company_fieldname = meta.get("fields", {"fieldtype": "Link",
"options": "Company"})[0].fieldname
if meta.issingle:
single = frappe.get_doc(doctype, doctype)
single.set(company_fieldname, "")
single.flags.ignore_mandatory = True
single.save()
else:
if not meta.issingle:
if not meta.istable:
# delete children
for df in meta.get_table_fields():

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
import urllib
from frappe.utils.nestedset import NestedSet
from frappe.website.website_generator import WebsiteGenerator
from frappe.website.render import clear_cache
@@ -91,7 +91,7 @@ def get_item_for_list_in_html(context):
# add missing absolute link in files
# user may forget it during upload
if (context.get("website_image") or "").startswith("files/"):
context["website_image"] = "/" + context["website_image"]
context["website_image"] = "/" + urllib.quote(context["website_image"])
return frappe.get_template("templates/includes/product_in_grid.html").render(context)
def get_group_item_count(item_group):

View File

@@ -12,7 +12,6 @@ from frappe.model.document import Document
class NamingSeriesNotSetError(frappe.ValidationError): pass
class NamingSeries(Document):
def get_transactions(self, arg=None):
doctypes = list(set(frappe.db.sql_list("""select parent
from `tabDocField` where fieldname='naming_series'""")
@@ -50,7 +49,7 @@ class NamingSeries(Document):
self.set_series_for(self.select_doc_for_series, series_list)
# create series
map(self.insert_series, [d.split('.')[0] for d in series_list])
map(self.insert_series, [d.split('.')[0] for d in series_list if d.strip()])
msgprint(_("Series Updated"))

View File

@@ -0,0 +1,167 @@
[
{
"allow_comments": 0,
"allow_delete": 0,
"allow_edit": 1,
"allow_multiple": 1,
"breadcrumbs": null,
"doc_type": "Address",
"docstatus": 0,
"doctype": "Web Form",
"introduction_text": null,
"login_required": 1,
"modified": "2015-06-01 06:53:43.699336",
"name": "addresses",
"page_name": "addresses",
"published": 1,
"success_message": null,
"success_url": "/addresses",
"title": "Addresses",
"web_form_fields": [
{
"default": null,
"description": "",
"fieldname": "address_title",
"fieldtype": "Data",
"hidden": 0,
"label": "Address Title",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "address_type",
"fieldtype": "Select",
"hidden": 0,
"label": "Address Type",
"options": "Billing\nShipping\nOffice\nPersonal\nPlant\nPostal\nShop\nSubsidiary\nWarehouse\nOther",
"read_only": 0,
"reqd": 1
},
{
"default": null,
"description": null,
"fieldname": "address_line1",
"fieldtype": "Data",
"hidden": 0,
"label": "Address Line 1",
"options": null,
"read_only": 0,
"reqd": 1
},
{
"default": null,
"description": null,
"fieldname": "address_line2",
"fieldtype": "Data",
"hidden": 0,
"label": "Address Line 2",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "city",
"fieldtype": "Data",
"hidden": 0,
"label": "City/Town",
"options": null,
"read_only": 0,
"reqd": 1
},
{
"default": null,
"description": null,
"fieldname": "state",
"fieldtype": "Data",
"hidden": 0,
"label": "State",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "pincode",
"fieldtype": "Data",
"hidden": 0,
"label": "Pincode",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "country",
"fieldtype": "Data",
"hidden": 0,
"label": "Country",
"options": "Country",
"read_only": 0,
"reqd": 1
},
{
"default": null,
"description": null,
"fieldname": null,
"fieldtype": "Column Break",
"hidden": null,
"label": null,
"options": null,
"read_only": null,
"reqd": null
},
{
"default": null,
"description": null,
"fieldname": "email_id",
"fieldtype": "Data",
"hidden": 0,
"label": "Email Id",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "phone",
"fieldtype": "Data",
"hidden": 0,
"label": "Phone",
"options": null,
"read_only": 0,
"reqd": 1
},
{
"default": "0",
"description": "",
"fieldname": "is_primary_address",
"fieldtype": "Check",
"hidden": 0,
"label": "Preferred Billing Address",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": "0",
"description": "",
"fieldname": "is_shipping_address",
"fieldtype": "Check",
"hidden": 0,
"label": "Preferred Shipping Address",
"options": null,
"read_only": 0,
"reqd": 0
}
],
"web_page_link_text": null
}
]

View File

@@ -0,0 +1,68 @@
[
{
"allow_comments": 1,
"allow_delete": 1,
"allow_edit": 1,
"allow_multiple": 1,
"breadcrumbs": "[{\"title\":\"Issues\", \"name\":\"issues\"}]",
"doc_type": "Issue",
"docstatus": 0,
"doctype": "Web Form",
"introduction_text": null,
"login_required": 1,
"modified": "2015-06-01 08:14:26.350792",
"name": "issues",
"page_name": "issues",
"published": 1,
"success_message": "",
"success_url": "/issues",
"title": "Issues",
"web_form_fields": [
{
"default": null,
"description": null,
"fieldname": "subject",
"fieldtype": "Data",
"hidden": 0,
"label": "Subject",
"options": null,
"read_only": 0,
"reqd": 1
},
{
"default": "Open",
"description": null,
"fieldname": "status",
"fieldtype": "Select",
"hidden": null,
"label": "Status",
"options": "Open\nReplied\nHold\nClosed",
"read_only": 1,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
"label": "Description",
"options": null,
"read_only": 0,
"reqd": 0
},
{
"default": null,
"description": null,
"fieldname": "attachment",
"fieldtype": "Attach",
"hidden": null,
"label": "Attachment",
"options": null,
"read_only": null,
"reqd": null
}
],
"web_page_link_text": null
}
]

View File

@@ -15,6 +15,7 @@ def after_install():
feature_setup()
from erpnext.setup.page.setup_wizard.setup_wizard import add_all_roles_to
add_all_roles_to("Administrator")
add_web_forms()
frappe.db.commit()
def feature_setup():
@@ -48,3 +49,12 @@ def set_single_defaults():
pass
frappe.db.set_default("date_format", "dd-mm-yyyy")
def add_web_forms():
"""Import web forms for Issues and Addresses"""
from frappe.modules.import_file import import_file_by_path
import_file_by_path(frappe.get_app_path("erpnext", "setup/fixtures/web_form/issues.json"),
data_import=True)
import_file_by_path(frappe.get_app_path("erpnext", "setup/fixtures/web_form/addresses.json"),
data_import=True)

View File

@@ -215,6 +215,7 @@ $.extend(erpnext.wiz, {
slide.get_field("language")
.set_input(erpnext.wiz.welcome.data.default_language || "english");
moment.locale("en");
}
});
},

View File

@@ -5,17 +5,18 @@ from __future__ import unicode_literals
import frappe
from frappe import throw, _
import frappe.defaults
from frappe.utils import flt, get_fullname, fmt_money, cstr
from frappe.utils import cint, flt, get_fullname, fmt_money, cstr
from erpnext.utilities.doctype.address.address import get_address_display
from frappe.utils.nestedset import get_root_of
class WebsitePriceListMissingError(frappe.ValidationError): pass
def set_cart_count(quotation=None):
if not quotation:
quotation = _get_cart_quotation()
cart_count = cstr(len(quotation.get("items")))
frappe.local.cookie_manager.set_cookie("cart_count", cart_count)
if cint(frappe.db.get_singles_value("Shopping Cart Settings", "enabled")):
if not quotation:
quotation = _get_cart_quotation()
cart_count = cstr(len(quotation.get("items")))
frappe.local.cookie_manager.set_cookie("cart_count", cart_count)
@frappe.whitelist()
def get_cart_quotation(doc=None):
@@ -29,7 +30,7 @@ def get_cart_quotation(doc=None):
return {
"doc": decorate_quotation_doc(doc),
"addresses": [{"name": address.name, "display": address.display}
for address in get_address_docs(party)],
for address in get_address_docs(party=party)],
"shipping_rules": get_applicable_shipping_rules(party)
}
@@ -281,12 +282,13 @@ def get_lead_or_customer():
return lead_doc
def get_address_docs(party=None):
def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None):
if not party:
party = get_lead_or_customer()
address_docs = frappe.db.sql("""select * from `tabAddress`
where `%s`=%s order by name""" % (party.doctype.lower(), "%s"), party.name,
where `{0}`=%s order by name limit {1}, {2}""".format(party.doctype.lower(),
limit_start, limit_page_length), party.name,
as_dict=True, update={"doctype": "Address"})
for address in address_docs:

View File

@@ -8,7 +8,7 @@ import frappe
from frappe import _, msgprint
from frappe.utils import comma_and
from frappe.model.document import Document
from frappe.utils.nestedset import get_ancestors_of
from frappe.utils.nestedset import get_ancestors_of, get_root_of
from erpnext.utilities.doctype.address.address import get_territory_from_address
class ShoppingCartSetupError(frappe.ValidationError): pass
@@ -42,7 +42,7 @@ class ShoppingCartSettings(Document):
return territory_name_map
def validate_price_lists(self):
territory_name_map = self.validate_overlapping_territories("price_lists", "selling_price_list")
self.validate_overlapping_territories("price_lists", "selling_price_list")
# validate that a Shopping Cart Price List exists for the default territory as a catch all!
price_list_for_default_territory = self.get_name_from_territory(self.default_territory, "price_lists",
@@ -131,7 +131,8 @@ class ShoppingCartSettings(Document):
def get_price_list(self, billing_territory):
price_list = self.get_name_from_territory(billing_territory, "price_lists", "selling_price_list")
if not (price_list and price_list[0]):
price_list = self.get_name_from_territory(self.default_territory, "price_lists", "selling_price_list")
price_list = self.get_name_from_territory(self.default_territory or get_root_of("Territory"),
"price_lists", "selling_price_list")
return price_list and price_list[0] or None
@@ -165,7 +166,7 @@ def is_cart_enabled():
return get_shopping_cart_settings().enabled
def get_default_territory():
return get_shopping_cart_settings().default_territory
return get_shopping_cart_settings().default_territory or get_root_of("Territory")
def check_shopping_cart_enabled():
if not get_shopping_cart_settings().enabled:

View File

@@ -6,7 +6,6 @@ from __future__ import unicode_literals
import frappe
from frappe import _
import frappe.defaults
from frappe.utils import cint
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import is_cart_enabled
def show_cart_count():
@@ -44,6 +43,6 @@ def update_my_account_context(context):
{"label": _("Orders"), "url": "orders"},
{"label": _("Invoices"), "url": "invoices"},
{"label": _("Shipments"), "url": "shipments"},
# {"label": _("Issues"), "url": "tickets"},
{"label": _("Issues"), "url": "issues"},
{"label": _("Addresses"), "url": "addresses"},
])

View File

@@ -65,7 +65,7 @@
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
@@ -523,7 +523,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:16.946934",
"modified": "2015-06-02 14:18:34.512236",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",

View File

@@ -90,7 +90,7 @@ class TestItem(unittest.TestCase):
"income_account": "Sales - _TC",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center 2 - _TC",
"qty": 0.0,
"qty": 1.0,
"price_list_rate": 100.0,
"base_price_list_rate": 0.0,
"discount_percentage": 0.0,

View File

@@ -221,7 +221,7 @@
"icon": "icon-ticket",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 15:36:06.818491",
"modified": "2015-06-09 05:47:05.934432",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",

View File

@@ -6,7 +6,13 @@ frappe.listview_settings['Material Request'] = {
} else if(doc.docstatus==1 && flt(doc.per_ordered) < 100) {
return [__("Pending"), "orange", "per_ordered,<,100"];
} else if(doc.docstatus==1 && flt(doc.per_ordered) == 100) {
return [__("Ordered"), "green", "per_ordered,=,100"];
if (doc.material_request_type == "Purchase") {
return [__("Ordered"), "green", "per_ordered,=,100"];
} else if (doc.material_request_type == "Material Transfer") {
return [__("Transfered"), "green", "per_ordered,=,100"];
} else if (doc.material_request_type == "Material Issue") {
return [__("Issued"), "green", "per_ordered,=,100"];
}
}
}
};

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