Compare commits

..

95 Commits

Author SHA1 Message Date
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
121 changed files with 2295 additions and 2258 deletions

View File

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

View File

@@ -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
},
@@ -171,7 +171,7 @@
"icon": "icon-money",
"idx": 1,
"in_create": 0,
"modified": "2015-04-27 20:07:37.147184",
"modified": "2015-05-28 14:10:40.606010",
"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

@@ -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

@@ -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:

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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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.20"
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

@@ -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

@@ -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,8 @@ 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

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

@@ -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

@@ -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

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

@@ -43,8 +43,8 @@ def get_so_details():
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)})
where customer = %s and docstatus = 1 order by transaction_date desc
limit 1""", customer)
return res and res[0][0] or 0

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

@@ -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'""")

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"];
}
}
}
};

View File

@@ -48,7 +48,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -264,7 +264,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-02-19 01:07:00.695393",
"modified": "2015-06-02 14:19:45.611733",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",

View File

@@ -4,6 +4,19 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "barcode",
"fieldtype": "Data",
"label": "Barcode",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "item_code",
"fieldtype": "Link",
@@ -49,7 +62,7 @@
{
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
"in_list_view": 0,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
@@ -642,7 +655,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-05-27 02:47:16.086625",
"modified": "2015-06-08 08:21:18.024324",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
import frappe.defaults
from frappe.utils import cstr, cint, flt, comma_or, nowdate, get_datetime
from frappe.utils import cstr, cint, flt, comma_or, get_datetime
from frappe import _
from erpnext.stock.utils import get_incoming_rate
@@ -185,11 +185,16 @@ class StockEntry(StockController):
def validate_production_order(self):
if self.purpose in ("Manufacture", "Material Transfer for Manufacture"):
if not self.bom_no:
frappe.throw(_("BOM No is mandatory"))
# check if production order is entered
if not self.production_order:
frappe.throw(_("Production order number is mandatory for stock entry purpose manufacture"))
# check for double entry
if self.purpose=="Manufacture":
if not self.fg_completed_qty:
frappe.throw(_("For Quantity (Manufactured Qty) is mandatory"))
self.check_if_operations_completed()
self.check_duplicate_entry_for_production_order()
elif self.purpose != "Material Transfer":
@@ -378,10 +383,21 @@ class StockEntry(StockController):
def validate_finished_goods(self):
"""validation: finished good quantity should be same as manufacturing quantity"""
items_with_target_warehouse = []
for d in self.get('items'):
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
format(d.idx, d.transfer_qty, self.fg_completed_qty))
if self.production_order and self.purpose == "Manufacture" and d.t_warehouse:
items_with_target_warehouse.append(d.item_code)
if self.production_order and self.purpose == "Manufacture":
production_item = frappe.db.get_value("Production Order",
self.production_order, "production_item")
if production_item not in items_with_target_warehouse:
frappe.throw(_("Finished Item {0} must be entered for Manufacture type entry")
.format(production_item))
def validate_return_reference_doc(self):
"""validate item with reference doc"""
@@ -399,7 +415,6 @@ class StockEntry(StockController):
# posting date check
ref_posting_datetime = "%s %s" % (ref.doc.posting_date, ref.doc.posting_time or "00:00:00")
this_posting_datetime = "%s %s" % (self.posting_date, self.posting_time)
if get_datetime(ref_posting_datetime) < get_datetime(ref_posting_datetime):
from frappe.utils.dateutils import datetime_in_user_format
@@ -474,9 +489,10 @@ class StockEntry(StockController):
pro_doc = frappe.get_doc("Production Order", self.production_order)
_validate_production_order(pro_doc)
pro_doc.run_method("update_status")
pro_doc.run_method("update_production_order_qty")
if self.purpose == "Manufacture":
self.update_planned_qty(pro_doc)
if self.fg_completed_qty:
pro_doc.run_method("update_production_order_qty")
if self.purpose == "Manufacture":
self.update_planned_qty(pro_doc)
def update_planned_qty(self, pro_doc):
from erpnext.stock.utils import update_bin
@@ -546,9 +562,6 @@ class StockEntry(StockController):
return ret
def get_items(self):
if not self.fg_completed_qty or not self.bom_no:
frappe.throw(_("BOM and Manufacturing Quantity are required"))
self.set('items', [])
self.validate_production_order()
@@ -638,17 +651,16 @@ class StockEntry(StockController):
issued_item_qty = self.get_issued_qty()
max_qty = flt(self.pro_doc.qty)
only_pending_fetched = []
for item in item_dict:
pending_to_issue = (max_qty * item_dict[item]["qty"]) - issued_item_qty.get(item, 0)
desire_to_transfer = flt(self.fg_completed_qty) * item_dict[item]["qty"]
if desire_to_transfer <= pending_to_issue:
item_dict[item]["qty"] = desire_to_transfer
else:
elif pending_to_issue > 0:
item_dict[item]["qty"] = pending_to_issue
if pending_to_issue:
only_pending_fetched.append(item)
else:
item_dict[item]["qty"] = 0
# delete items with 0 qty
for item in item_dict.keys():
@@ -659,9 +671,6 @@ class StockEntry(StockController):
if not len(item_dict):
frappe.msgprint(_("""All items have already been transferred for this Production Order."""))
elif only_pending_fetched:
frappe.msgprint(_("Pending Items {0} updated").format(only_pending_fetched))
return item_dict
def get_issued_qty(self):

View File

@@ -163,8 +163,8 @@ def get_basic_details(args, item):
"uom": item.stock_uom,
"min_order_qty": flt(item.min_order_qty) if args.parenttype == "Material Request" else "",
"conversion_factor": 1.0,
"qty": args.qty or 0.0,
"stock_qty": 0.0,
"qty": args.qty or 1.0,
"stock_qty": 1.0,
"price_list_rate": 0.0,
"base_price_list_rate": 0.0,
"rate": 0.0,

View File

@@ -66,7 +66,7 @@
"oldfieldtype": "Data",
"options": "Email",
"permlevel": 0,
"reqd": 1
"reqd": 0
},
{
"fieldname": "fold",
@@ -229,11 +229,19 @@
"hidden": 1,
"label": "Content Type",
"permlevel": 0
},
{
"fieldname": "attachment",
"fieldtype": "Attach",
"hidden": 1,
"label": "Attachment",
"permlevel": 0,
"precision": ""
}
],
"icon": "icon-ticket",
"idx": 1,
"modified": "2015-05-28 03:21:04.690112",
"modified": "2015-06-01 08:14:01.750421",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",

View File

@@ -17,6 +17,8 @@ class Issue(Document):
return "{0}: {1}".format(_(self.status), self.subject)
def validate(self):
if not self.raised_by:
self.raised_by = frappe.session.user
self.update_status()
self.set_lead_contact(self.raised_by)
@@ -54,7 +56,8 @@ class Issue(Document):
def get_list_context(context=None):
return {
"title": _("My Issues"),
"get_list": get_issue_list
"get_list": get_issue_list,
"row_template": "templates/includes/issue_row.html"
}
def get_issue_list(doctype, txt, filters, limit_start, limit_page_length=20):
@@ -84,3 +87,6 @@ def set_multiple_status(names, status):
names = json.loads(names)
for name in names:
set_status(name, status)
def has_website_permission(doc, ptype, user, verbose=False):
return doc.raised_by==user

View File

@@ -1,6 +1,6 @@
{% $.each(visible_columns || [], function(i, df) { %}
{% var val = doc.get_formatted(df.fieldname);
if((df.fieldname !== "description") && val) { %}
if((df.fieldname !== "description" && df.fieldname !== "item_name") && val) { %}
<div class="row">
<div class="col-xs-4 text-ellipsis">
<strong title="{%= __(df.label) %}">{%= __(df.label) %}:</strong>

View File

@@ -1,4 +1,4 @@
{% var visible_columns = row.get_visible_columns(["item_code", "item_name", "description", "qty", "rate", "amount", "stock_uom", "uom", "discount_percentage", "schedule_date", "warehouse", "against_sales_order", "sales_order"]); %}
{% var visible_columns = row.get_visible_columns(["item_code", "qty", "rate", "amount", "stock_uom", "uom", "discount_percentage", "schedule_date", "warehouse", "against_sales_order", "sales_order"]); %}
{% if(!doc) { %}
<div class="row">
@@ -8,6 +8,7 @@
<div class="col-sm-2 col-xs-4 text-right">{%= __("Amount") %}</div>
</div>
{% } else { %}
{% var visible_column_fieldnames = $.map(visible_columns, function(x, i) {return x.fieldname}); %}
<div class="row">
<div class="col-sm-6 col-xs-8">
{% if(doc.warehouse) {
@@ -45,8 +46,14 @@
<strong>{%= doc.item_code %}</strong>
{% } %}
{% if(doc.item_name != doc.item_code) { %}
{% if(doc.item_name != doc.item_code && in_list(visible_column_fieldnames, "item_name")) { %}
<br>{%= doc.item_name %}{% } %}
{% if((doc.description != doc.item_code != doc.item_name) &&
in_list(visible_column_fieldnames, "description")) { %}
<br>
<strong>Description: </strong>
{%= doc.get_formatted("description") %}{% } %}
{% include "templates/form_grid/includes/visible_cols.html" %}
</div>

View File

@@ -1,5 +1,5 @@
{% var visible_columns = row.get_visible_columns(["item_code", "warehouse",
"item_name", "description", "amount", "stock_uom", "uom", "qty", "schedule_date"]); %}
"item_name", "amount", "stock_uom", "uom", "qty", "schedule_date"]); %}
{% if(!doc) { %}
<div class="row">

View File

@@ -1,5 +1,5 @@
{% var visible_columns = row.get_visible_columns(["item_code",
"item_name", "description", "amount", "stock_uom", "uom", "qty",
"item_name", "amount", "stock_uom", "uom", "qty",
"s_warehouse", "t_warehouse", "incoming_rate"]);
%}

View File

@@ -2,10 +2,13 @@
{% block header %}<h2>{{ title }}</h2>{% endblock %}
{% block header_actions %}
{% include 'templates/includes/product_search_box.html' %}
{% endblock %}
{% block content %}
{% from "erpnext/templates/includes/macros.html" import product_image %}
<div class="item-content">
{% include 'templates/includes/product_search_box.html' %}
<div class="product-page-content" itemscope itemtype="http://schema.org/Product">
<div class="row">
<div class="col-sm-5">

View File

@@ -1,6 +1,9 @@
{% block header_actions %}
{% include 'templates/includes/product_search_box.html' %}
{% endblock %}
{% block content %}
<div class="item-group-content">
{% include 'templates/includes/product_search_box.html' %}
<div>
{% if slideshow %}<!-- slideshow -->
{% include "templates/includes/slideshow.html" %}

View File

@@ -0,0 +1,20 @@
<div class="web-list-item">
<a href="/addresses?name={{ doc.name }}" no-pjax>
<div class="row">
<div class="col-sm-4">
<span class="strong">{{ doc.address_title }}</span>
</div>
<div class="col-sm-2">
{{ doc.address_type }}
</div>
<div class="col-sm-4">
{{ doc.address_line1 }}<br>
{% if doc.address_line2 %}{{ doc.address_line2 }}<br>{% endif %}
{{ doc.city }}<br>
</div>
<div class="col-sm-2">
{% if doc.state %}{{ doc.state }}, {% endif %}{{ doc.country }}
</div>
</div>
</a>
</div>

View File

@@ -0,0 +1,16 @@
<div class="web-list-item">
<div class="row">
<div class="col-sm-8">
<a class="no-decoration" href="/issues?name={{ doc.name }}" no-pjax>
{{ doc.subject }}
</a>
</div>
<div class="col-sm-2">
<span class="indicator {{ "red" if doc.status=="Open" else "blue" }}">
{{ doc.status }}</span>
</div>
<div class="col-sm-2 text-muted text-right small">
{{ frappe.format_date(doc.creation) }}
</div>
</div>
</div>

View File

@@ -1,6 +1,6 @@
{% from "erpnext/templates/includes/macros.html" import product_image_square %}
<a class="product-link" href="{{ (route or page_name)|with_leading_slash }}">
<a class="product-link" href="{{ (route or page_name)|abs_url }}">
<div class="col-sm-2 col-xs-4 product-image-wrapper">
{{ product_image_square(website_image) }}
<div class="text-ellipsis inline-block small product-text">{{ item_name }}</div>

View File

@@ -1,15 +1,15 @@
<!-- TODO product listing -->
<div class="container content">
<div style="height: 120px; overflow: hidden;">
<a href="{{ (route or page_name)|with_leading_slash }}">
<a href="{{ (route or page_name)|abs_url }}">
{%- if website_image -%}
<img class="product-image" style="width: 80%; margin: auto;" src="{{ website_image|with_leading_slash }}">
<img class="product-image" style="width: 80%; margin: auto;" src="{{ website_image|abs_url }}">
{%- else -%}
<div style="width: 80%; height: 120px; background-color: #F7FAFC;"></div>
{%- endif -%}
</a>
</div>
<div style="height: 100px; overflow: hidden; font-size: 80%;">
<div><a href="{{ (route or page_name)|with_leading_slash }}">{{ item_name }}</a></div>
<div><a href="{{ (route or page_name)|abs_url }}">{{ item_name }}</a></div>
</div>
</div>

View File

@@ -1,20 +1,17 @@
<div class="product-search pull-right">
<form class="form-inline form-search">
<div class="input-group">
<input class="form-control" type="text" id="product-search"
placeholder="Product Search...">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="btn-product-search">
<i class="icon-search"></i></button>
</span>
</div>
</form>
</div>
<script>
frappe.ready(function() {
$(".product-search").remove();
$('<div class="product-search pull-right">\
<form class="form-inline form-search">\
<div class="input-group">\
<input class="form-control" type="text" id="product-search" placeholder="Product Search...">\
<span class="input-group-btn">\
<button class="btn btn-default" type="button" id="btn-product-search">\
<i class="icon-search"></i></button>\
</span>\
</div>\
</form>\
</div>').prependTo(".page-header-block");
$('.dropdown-toggle').dropdown();
$("#btn-product-search").click(function() {
var txt = $("#product-search").val();
if(txt) {

View File

@@ -1,5 +1,6 @@
{% set doc = frappe.get_doc(doc) %}
<a class="website-list-row" href="/{{ pathname }}/{{ doc.name }}" no-pjax>
<div class="web-list-item">
<a href="/{{ pathname }}/{{ doc.name }}" no-pjax>
<div class="row">
<div class="col-sm-6 col-xs-7">
<div class="row">
@@ -12,7 +13,7 @@
<span class="indicator orange">{{ doc.status_display }}</span>
{%- endif -%}
{%- elif doc.status -%}
<span class="indicator">{{ doc.status }}</span>
<span class="indicator blue">{{ doc.status }}</span>
{%- endif -%}
</div>
</div>
@@ -27,4 +28,4 @@
{{ frappe.utils.pretty_date(doc.creation) }}</div>
</div>
</a>
</div>

View File

@@ -1,112 +0,0 @@
{% block title %} {{ title }} {% endblock %}
{% block header %}<h2>{{ title }}</h2>{% endblock %}
{% block content %}
{% macro render_fields(docfields) -%}
{% for df in docfields -%}
{% if df.fieldtype == "Data" -%}
<fieldset>
<label>{{ df.label }}</label>
<input class="form-control" type="text" placeholder="Type {{ df.label }}"
data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}"
{% if doc and doc.get(df.fieldname) -%} value="{{ doc[df.fieldname] }}" {%- endif %}>
</fieldset>
{% elif df.fieldtype == "Check" -%}
<fieldset class="checkbox">
<label><input type="checkbox" data-fieldname="{{ df.fieldname }}"
data-fieldtype="{{ df.fieldtype }}"
{% if doc and frappe.utils.cint(doc.get(df.fieldname)) -%} checked="checked" {%- endif %}>
{{ df.label }}</label>
</fieldset>
{% elif df.fieldtype in ("Select", "Link") -%}
<fieldset>
{% set select_options = frappe.get_list(df.options)|map(attribute="name")
if df.fieldtype == "Link" else df.options.split("\n") %}
<label>{{ df.label }}</label>
<select class="form-control" data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}">
{% for value in select_options -%}
{% if doc and doc.get(df.fieldname) == value -%}
<option selected="selected">{{ value }}</option>
{% else -%}
<option>{{ value }}</option>
{%- endif %}
{%- endfor %}
</select>
</fieldset>
{%- endif %}
{%- endfor %}
{%- endmacro %}
<div class="container content">
<ul class="breadcrumb">
<li><a href="/index">Home</a></li>
<li><a href="/addresses">My Addresses</a></li>
<li class="active"><i class="icon-map-marker icon-fixed-width"></i> {{ title }}</li>
</ul>
<h3><i class="icon-map-marker icon-fixed-width"></i> {{ title }}</h3>
<button type="button" class="btn btn-primary pull-right" id="address-save"><i class="icon-ok"></i>
{{ doc and "Save" or "Insert" }}</button>
<div class="clearfix"></div>
<hr>
<div id="address-error" class="alert alert-danger" style="display:none"></div>
<form autocomplete="on">
<div class="row">
<section class="col-md-6">
{{ render_fields(meta.left_fields) }}
</section>
<section class="col-md-6">
{{ render_fields(meta.right_fields) }}
</section>
</section>
</form>
</div>
<script>
;(function() {
console.log("yoyo");
frappe.ready(function() {
bind_save();
});
var bind_save = function() {
$("#address-save").on("click", function() {
console.log("clicked!");
var fields = {
name: "{{ docname or '' }}"
};
$("form").find("[data-fieldname]").each(function(i, input) {
var $input = $(input);
var fieldname = $(input).attr("data-fieldname");
var fieldtype = $(input).attr("data-fieldtype");
if(fieldtype == "Check") {
fields[fieldname] = $input.is(":checked") ? 1 : 0;
} else {
fields[fieldname] = $input.val();
}
});
frappe.call({
btn: $(this),
type: "POST",
method: "erpnext.templates.pages.address.save_address",
args: { fields: fields, address_fieldname: get_url_arg("address_fieldname") },
error_msg: "#address-error",
callback: function(r) {
if(get_url_arg("address_fieldname")) {
window.location.href = "cart";
} else {
window.location.href = "address?name=" + encodeURIComponent(r.message);
}
}
});
});
};
})();
</script>
<!-- no-sidebar -->
{% endblock %}

View File

@@ -1,62 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import json
import frappe
from erpnext.shopping_cart.cart import get_lead_or_customer, update_cart_address
from frappe.desk.form.meta import get_meta
no_cache = 1
no_sitemap = 1
def get_context(context):
def _get_fields(fieldnames):
return [frappe._dict(zip(["label", "fieldname", "fieldtype", "options"],
[df.label, df.fieldname, df.fieldtype, df.options]))
for df in get_meta("Address").get("fields", {"fieldname": ["in", fieldnames]})]
docname = doc = None
title = "New Address"
if frappe.form_dict.name:
doc = frappe.get_doc("Address", frappe.form_dict.name)
docname = doc.name
title = doc.name
return {
"doc": doc,
"meta": frappe._dict({
"left_fields": _get_fields(["address_title", "address_type", "address_line1", "address_line2",
"city", "state", "pincode", "country"]),
"right_fields": _get_fields(["email_id", "phone", "fax", "is_primary_address",
"is_shipping_address"])
}),
"docname": docname,
"title": title
}
@frappe.whitelist()
def save_address(fields, address_fieldname=None):
party = get_lead_or_customer()
fields = json.loads(fields)
if fields.get("name"):
doc = frappe.get_doc("Address", fields.get("name"))
else:
doc = frappe.get_doc({"doctype": "Address", "__islocal": 1})
doc.update(fields)
party_fieldname = party.doctype.lower()
doc.update({
party_fieldname: party.name,
(party_fieldname + "_name"): party.get(party_fieldname + "_name")
})
doc.flags.ignore_permissions = True
doc.save()
if address_fieldname:
update_cart_address(address_fieldname, doc.name)
return doc.name

View File

@@ -1,50 +0,0 @@
{% block title %} {{ "My Addresses" }} {% endblock %}
{% block header %}<h2>My Addresses</h2>{% endblock %}
{% block breadcrumbs %}{% include "templates/includes/breadcrumbs.html" %}{% endblock %}
{% block content %}
<div class="addresses-content">
<p><a class="btn btn-default" href="/address"><i class="icon-plus"> New Address</i></a></p>
<hr>
<div id="address-list">
<div class="text-muted progress">{{ _("Loading") }}...</div>
</div>
</div>
<script>
;(function() {
var fetch_addresses = function() {
frappe.call({
method: "erpnext.templates.pages.addresses.get_addresses",
callback: function(r) {
$("#address-list .progress").remove();
var $list = $("#address-list");
if(!(r.message && r.message.length)) {
$list.html("<div class='alert'>No Addresses Found</div>");
return;
}
$.each(r.message, function(i, address) {
address.url_name = encodeURIComponent(address.name);
$(repl('<div> \
<p><a href="/address?name=%(url_name)s">%(name)s</a></p> \
<p>%(display)s</p> \
<hr> \
</div>', address)).appendTo($list);
});
}
});
};
$(document).ready(function() {
fetch_addresses();
});
})();
</script>
<!-- no-sidebar -->
{% endblock %}

View File

@@ -1,13 +0,0 @@
# 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
from erpnext.shopping_cart.cart import get_address_docs
no_cache = 1
no_sitemap = 1
@frappe.whitelist()
def get_addresses():
return get_address_docs()

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