Compare commits
245 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ad168ac67 | ||
|
|
3e9520b276 | ||
|
|
ad6cf4fa88 | ||
|
|
29b74b90c8 | ||
|
|
e927b81292 | ||
|
|
88a37c17a6 | ||
|
|
5fe7f6c3fd | ||
|
|
d59819d9bb | ||
|
|
afdd7a626c | ||
|
|
7699b5e92a | ||
|
|
b5d765d19a | ||
|
|
6d03790b44 | ||
|
|
3638250f5d | ||
|
|
7bf192e46a | ||
|
|
fa351f4bdf | ||
|
|
bedb486c55 | ||
|
|
f3f0dfef2a | ||
|
|
5d5a81f375 | ||
|
|
02c8607d04 | ||
|
|
ddd4845420 | ||
|
|
63b06420e1 | ||
|
|
bf66d7e041 | ||
|
|
fc85768685 | ||
|
|
37c784eb3a | ||
|
|
a54eb7d022 | ||
|
|
48af4289d3 | ||
|
|
03c30a7f92 | ||
|
|
949a920022 | ||
|
|
852cb64e4f | ||
|
|
b66fb9a4c0 | ||
|
|
9fbdf14e61 | ||
|
|
4b7a30b527 | ||
|
|
5ad4a6e161 | ||
|
|
10a4a13e5e | ||
|
|
3ceab64bfa | ||
|
|
6015f0f2ec | ||
|
|
e5ca48a76a | ||
|
|
3e4bcfe2d8 | ||
|
|
5e4c8ecd62 | ||
|
|
11df066ed0 | ||
|
|
87f2848aeb | ||
|
|
12450fa473 | ||
|
|
67bbcf6932 | ||
|
|
79918c66c2 | ||
|
|
960208bae0 | ||
|
|
1bad1fcc00 | ||
|
|
43ef4e9047 | ||
|
|
65f6f2a05e | ||
|
|
558fcc140f | ||
|
|
ea92682cfd | ||
|
|
a06a600d0a | ||
|
|
af9d3a4db6 | ||
|
|
f39a9f1c5b | ||
|
|
067991ee30 | ||
|
|
1589ada04d | ||
|
|
ee368221cf | ||
|
|
6691856d08 | ||
|
|
53de2f1b57 | ||
|
|
22aaf0cbd0 | ||
|
|
8ebc0df65f | ||
|
|
4095915bff | ||
|
|
abe8e2ecce | ||
|
|
b053674781 | ||
|
|
bb68f8ca01 | ||
|
|
943637e06c | ||
|
|
0407cb0d92 | ||
|
|
d192a420d1 | ||
|
|
3856d14ae6 | ||
|
|
85480b3af7 | ||
|
|
c4125b32ee | ||
|
|
4e08dfc72f | ||
|
|
53e34f5c1c | ||
|
|
c6e1c3c048 | ||
|
|
0c2de6e07a | ||
|
|
b801357ecf | ||
|
|
1508267fd6 | ||
|
|
8f1f93603d | ||
|
|
f1bd39c937 | ||
|
|
800c69eec3 | ||
|
|
ec252c806f | ||
|
|
2a903a0608 | ||
|
|
71b4e48ea5 | ||
|
|
ae2d92ee76 | ||
|
|
21cf1fd851 | ||
|
|
02c281cc2f | ||
|
|
a938d3956a | ||
|
|
02b0ed4199 | ||
|
|
76f93d05b7 | ||
|
|
24ab20fe11 | ||
|
|
1eb31db71f | ||
|
|
ef95b4d6e3 | ||
|
|
514c0417dd | ||
|
|
67f6ac848c | ||
|
|
5d95ebec4e | ||
|
|
bb7317d398 | ||
|
|
550268eaf3 | ||
|
|
7f9af46da5 | ||
|
|
e38eb83358 | ||
|
|
af00c9f70b | ||
|
|
5c7545da0c | ||
|
|
d6e8bb5452 | ||
|
|
435032f5bc | ||
|
|
1ef50c89db | ||
|
|
2e4b4454b3 | ||
|
|
4b33b7e1c1 | ||
|
|
69279229cc | ||
|
|
5b7028c7bb | ||
|
|
0018db344c | ||
|
|
e9a4f4e70d | ||
|
|
be03de3ad6 | ||
|
|
d235325a95 | ||
|
|
6daa6e422e | ||
|
|
07913c3ff2 | ||
|
|
71ba7ea717 | ||
|
|
3b0e6cecd6 | ||
|
|
544de60d36 | ||
|
|
d652221071 | ||
|
|
4d5d3b7685 | ||
|
|
3bf9071598 | ||
|
|
46af07cc09 | ||
|
|
27692670b1 | ||
|
|
3708df61bf | ||
|
|
3f2dd04b10 | ||
|
|
fd598d8f3a | ||
|
|
4e0999dda7 | ||
|
|
eef3f62ff7 | ||
|
|
104eb8c6ad | ||
|
|
3959c7c3c1 | ||
|
|
b43f4073db | ||
|
|
01659271be | ||
|
|
c616a4a527 | ||
|
|
eb7eb43dfc | ||
|
|
00ae424cac | ||
|
|
7b6e09b9a7 | ||
|
|
90a3e60de7 | ||
|
|
f3e91e2b2b | ||
|
|
846f5d4bd8 | ||
|
|
51520f9de6 | ||
|
|
9d457d3e34 | ||
|
|
8ddd946dea | ||
|
|
c20abf6b2a | ||
|
|
68a48c9cfc | ||
|
|
8c3f99f12e | ||
|
|
9b09ff29d2 | ||
|
|
f4e908bd91 | ||
|
|
5d8803b23e | ||
|
|
f970ca4d35 | ||
|
|
29cebbb0cd | ||
|
|
0b078fb4cb | ||
|
|
89d001caf3 | ||
|
|
6837e69187 | ||
|
|
5824ae98d9 | ||
|
|
67526f244e | ||
|
|
67cbeb1bb0 | ||
|
|
8859eb23a3 | ||
|
|
ae450fc23b | ||
|
|
82e816054e | ||
|
|
ea7768d3f3 | ||
|
|
cb650f836e | ||
|
|
f4fc30a72d | ||
|
|
095701e86b | ||
|
|
dccceb44f9 | ||
|
|
5f389c999a | ||
|
|
29fa0a9a17 | ||
|
|
c1d22adb9f | ||
|
|
bce13cd0e3 | ||
|
|
81bb2c9f3c | ||
|
|
3bf5a38c6f | ||
|
|
c93de0e803 | ||
|
|
d03203966a | ||
|
|
8623166dca | ||
|
|
577e4c4e28 | ||
|
|
ebaea08225 | ||
|
|
1a78a3244b | ||
|
|
8f51a5e527 | ||
|
|
1d962dd3f7 | ||
|
|
bbf81aa3a4 | ||
|
|
862302f02d | ||
|
|
408336e7ad | ||
|
|
ab49c3100d | ||
|
|
ec27a30069 | ||
|
|
5e994ddf65 | ||
|
|
4eced4acec | ||
|
|
6df26422f6 | ||
|
|
a951e56f9c | ||
|
|
1f8e5fbcb1 | ||
|
|
ca6fed359b | ||
|
|
9961fb82d6 | ||
|
|
8326028d33 | ||
|
|
666d004b40 | ||
|
|
9a8f33f855 | ||
|
|
8181a7463e | ||
|
|
ac08fbd438 | ||
|
|
210b6f8f7e | ||
|
|
25366a22ad | ||
|
|
919a74ad88 | ||
|
|
b3c8f44b3e | ||
|
|
94500fd17b | ||
|
|
dcd54209fc | ||
|
|
759f669214 | ||
|
|
70eca9462b | ||
|
|
60d9446656 | ||
|
|
934105bf34 | ||
|
|
26b8f5c3ce | ||
|
|
36693e27be | ||
|
|
a5d5403bf3 | ||
|
|
0e35651e94 | ||
|
|
837ffbddbc | ||
|
|
ff25573558 | ||
|
|
82a199d6d7 | ||
|
|
d15a507567 | ||
|
|
01e79f033e | ||
|
|
9a6e675b41 | ||
|
|
7331f169fc | ||
|
|
d09f35fa98 | ||
|
|
52d703a232 | ||
|
|
e4e00d2215 | ||
|
|
60944e3397 | ||
|
|
0b642cd414 | ||
|
|
b4de1c771b | ||
|
|
aedaac63ea | ||
|
|
2cb598f644 | ||
|
|
bbe9bccc1a | ||
|
|
04c8bf0b21 | ||
|
|
0a9176a647 | ||
|
|
66e2a510b9 | ||
|
|
f070c548de | ||
|
|
96e629a635 | ||
|
|
ac3ad0810a | ||
|
|
1e96b7bbe5 | ||
|
|
0ea5d941e6 | ||
|
|
881491cd2b | ||
|
|
2c77165fc6 | ||
|
|
6561b8ade9 | ||
|
|
840c757b12 | ||
|
|
7055446508 | ||
|
|
e0434ad40e | ||
|
|
d53dd7f4c9 | ||
|
|
fed9816213 | ||
|
|
a35839aa47 | ||
|
|
5491275b66 | ||
|
|
70fe968f02 | ||
|
|
a3aa6a4449 | ||
|
|
8fa1e03367 | ||
|
|
0f0b121669 |
@@ -131,6 +131,7 @@
|
||||
"getCookies": true,
|
||||
"get_url_arg": true,
|
||||
"get_server_fields": true,
|
||||
"set_multiple": true
|
||||
"set_multiple": true,
|
||||
"QUnit": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
language: python
|
||||
dist: trusty
|
||||
group: deprecated-2017Q2
|
||||
|
||||
python:
|
||||
- "2.7"
|
||||
|
||||
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@frappe.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -2,8 +2,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
__version__ = '8.1.0'
|
||||
|
||||
__version__ = '8.3.1'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -62,13 +62,13 @@ class BankReconciliation(Document):
|
||||
|
||||
for d in entries:
|
||||
row = self.append('payment_entries', {})
|
||||
|
||||
d.amount = fmt_money(d.debit if d.debit else d.credit, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr"))
|
||||
amount = d.debit if d.debit else d.credit
|
||||
d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr"))
|
||||
d.pop("credit")
|
||||
d.pop("debit")
|
||||
d.pop("account_currency")
|
||||
row.update(d)
|
||||
self.total_amount += flt(d.amount)
|
||||
self.total_amount += flt(amount)
|
||||
|
||||
def update_clearance_date(self):
|
||||
clearance_date_updated = False
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
@@ -10,6 +11,7 @@
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -20,7 +22,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Document",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -30,6 +34,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -37,17 +42,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"columns": 2,
|
||||
"fieldname": "payment_entry",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Entry",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -58,6 +66,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -66,6 +75,7 @@
|
||||
"width": "50"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -76,7 +86,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Against Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -86,6 +98,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -94,6 +107,7 @@
|
||||
"width": "15"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -104,7 +118,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -115,6 +131,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -122,6 +139,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -132,7 +150,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@@ -140,6 +160,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -148,6 +169,7 @@
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -158,7 +180,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Posting Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -168,6 +192,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -175,17 +200,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"columns": 2,
|
||||
"fieldname": "cheque_number",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Cheque Number",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -195,6 +223,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -202,6 +231,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -212,7 +242,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Cheque Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -222,6 +254,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -229,6 +262,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -239,7 +273,9 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Clearance Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -249,6 +285,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -256,18 +293,18 @@
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-11-17 11:39:00.308624",
|
||||
"modified": "2017-06-23 12:07:50.883515",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Reconciliation Detail",
|
||||
@@ -276,6 +313,8 @@
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -733,11 +733,10 @@ def get_opening_accounts(company):
|
||||
accounts = frappe.db.sql_list("""select
|
||||
name from tabAccount
|
||||
where
|
||||
is_group=0 and
|
||||
report_type='Balance Sheet' and
|
||||
ifnull(warehouse, '') = '' and
|
||||
company=%s
|
||||
order by name asc""", company)
|
||||
is_group=0 and report_type='Balance Sheet' and company=%s and
|
||||
name not in(select distinct account from tabWarehouse where
|
||||
account is not null and account != '')
|
||||
order by name asc""", frappe.db.escape(company))
|
||||
|
||||
return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
|
||||
|
||||
|
||||
@@ -224,9 +224,9 @@ cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
|
||||
return {
|
||||
filters: [
|
||||
["Account", "account_type", "in", ["Cash", "Bank"]],
|
||||
["Account", "root_type", "=", "Asset"],
|
||||
["Account", "is_group", "=",0],
|
||||
["Account", "company", "=", doc.company]
|
||||
["Account", "company", "=", doc.company],
|
||||
["Account", "report_type", "=", "Balance Sheet"]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3238,7 +3238,7 @@
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@@ -3767,10 +3767,11 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-06-13 14:28:57.930167",
|
||||
"modified": "2017-06-29 10:48:09.707735",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
"name_case": "Title Case",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
|
||||
@@ -71,17 +71,19 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
});
|
||||
|
||||
if(!from_delivery_note && !is_delivered_by_supplier) {
|
||||
cur_frm.add_custom_button(__('Delivery'), cur_frm.cscript['Make Delivery Note'],
|
||||
__("Make"));
|
||||
cur_frm.add_custom_button(__('Delivery'),
|
||||
cur_frm.cscript['Make Delivery Note'], __("Make"));
|
||||
}
|
||||
}
|
||||
|
||||
if(doc.outstanding_amount!=0 && !cint(doc.is_return)) {
|
||||
cur_frm.add_custom_button(__('Payment'), this.make_payment_entry, __("Make"));
|
||||
cur_frm.add_custom_button(__('Payment'),
|
||||
this.make_payment_entry, __("Make"));
|
||||
}
|
||||
|
||||
if(doc.outstanding_amount>0 && !cint(doc.is_return)) {
|
||||
cur_frm.add_custom_button(__('Payment Request'), this.make_payment_request, __("Make"));
|
||||
cur_frm.add_custom_button(__('Payment Request'),
|
||||
this.make_payment_request, __("Make"));
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +305,23 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
}
|
||||
|
||||
this.frm.refresh_fields();
|
||||
},
|
||||
|
||||
company_address: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.company_address) {
|
||||
frappe.call({
|
||||
method: "frappe.contacts.doctype.address.address.get_address_display",
|
||||
args: {"address_dict": this.frm.doc.company_address },
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
me.frm.set_value("company_address_display", r.message)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.frm.set_value("company_address_display", "");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -324,11 +343,13 @@ cur_frm.cscript.hide_fields = function(doc) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var item_fields_stock = ['batch_no', 'actual_batch_qty', 'actual_qty', 'expense_account',
|
||||
'warehouse', 'expense_account', 'quality_inspection']
|
||||
cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock,
|
||||
(cint(doc.update_stock)==1 || cint(doc.is_return)==1 ? true : false));
|
||||
|
||||
|
||||
// India related fields
|
||||
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
|
||||
else hide_field(['c_form_applicable', 'c_form_no']);
|
||||
@@ -481,7 +502,7 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
'Delivery Note': 'Delivery',
|
||||
'Sales Invoice': 'Sales Return',
|
||||
'Payment Request': 'Payment Request',
|
||||
'Payment': 'Payment Entry'
|
||||
'Payment Entry': 'Payment'
|
||||
},
|
||||
frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(doc, cdt, cdn){
|
||||
return{
|
||||
@@ -502,8 +523,20 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
frm.set_query('company_address', function(doc) {
|
||||
if(!doc.company) {
|
||||
frappe.throw(_('Please set Company'));
|
||||
}
|
||||
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.address.address.address_query',
|
||||
filters: {
|
||||
link_doctype: 'Company',
|
||||
link_name: doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
project: function(frm){
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -200,37 +200,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "due_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Due Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "due_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -253,7 +222,7 @@
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Project",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -314,7 +283,7 @@
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -345,7 +314,7 @@
|
||||
"options": "POS Profile",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -510,6 +479,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "due_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payment Due Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "due_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -844,6 +844,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Territory",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -940,21 +971,21 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "customer_group",
|
||||
"fieldname": "company_address",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Customer Group",
|
||||
"label": "Company Address Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer Group",
|
||||
"options": "Address",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
@@ -971,24 +1002,23 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"fieldname": "company_address_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Territory",
|
||||
"label": "Company Address",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -1479,7 +1509,7 @@
|
||||
"options": "Sales Invoice Timesheet",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -1882,6 +1912,36 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "sec_tax_breakup",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item-wise Tax Breakup",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -1889,7 +1949,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "HTML",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -1899,12 +1959,12 @@
|
||||
"in_standard_filter": 0,
|
||||
"label": "Taxes and Charges Calculation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldtype": "HTML",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -2511,7 +2571,7 @@
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Outstanding Amount",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
@@ -2984,7 +3044,7 @@
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -3489,6 +3549,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Customer Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer Group",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -3566,7 +3657,7 @@
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
@@ -4419,7 +4510,7 @@
|
||||
"options": "Print Format",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -4480,7 +4571,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -4511,7 +4602,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@@ -4596,10 +4687,11 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-06-16 17:07:55.483734",
|
||||
"modified": "2017-07-04 17:11:09.477003",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
"name_case": "Title Case",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
|
||||
@@ -54,7 +54,10 @@ class SalesInvoice(SellingController):
|
||||
def validate(self):
|
||||
super(SalesInvoice, self).validate()
|
||||
self.validate_auto_set_posting_time()
|
||||
self.so_dn_required()
|
||||
|
||||
if not self.is_pos:
|
||||
self.so_dn_required()
|
||||
|
||||
self.validate_proj_cust()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
@@ -128,7 +131,8 @@ class SalesInvoice(SellingController):
|
||||
if not self.is_return:
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
self.check_credit_limit()
|
||||
self.update_serial_no()
|
||||
|
||||
self.update_serial_no()
|
||||
|
||||
if not cint(self.is_pos) == 1 and not self.is_return:
|
||||
self.update_against_document_in_jv()
|
||||
@@ -790,19 +794,18 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def update_serial_no(self, in_cancel=False):
|
||||
""" update Sales Invoice refrence in Serial No """
|
||||
invoice = None if (in_cancel or self.is_return) else self.name
|
||||
if in_cancel and self.is_return:
|
||||
invoice = self.return_against
|
||||
|
||||
for item in self.items:
|
||||
if not item.serial_no:
|
||||
continue
|
||||
|
||||
serial_nos = ["'%s'"%serial_no for serial_no in item.serial_no.split("\n")]
|
||||
|
||||
frappe.db.sql(""" update `tabSerial No` set sales_invoice='{invoice}'
|
||||
where name in ({serial_nos})""".format(
|
||||
invoice='' if in_cancel else self.name,
|
||||
serial_nos=",".join(serial_nos)
|
||||
)
|
||||
)
|
||||
for serial_no in item.serial_no.split("\n"):
|
||||
sno = frappe.get_doc('Serial No', serial_no)
|
||||
sno.sales_invoice = invoice
|
||||
sno.db_update()
|
||||
|
||||
def validate_serial_numbers(self):
|
||||
"""
|
||||
|
||||
@@ -1105,6 +1105,22 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
for i, k in enumerate(expected_values["keys"]):
|
||||
self.assertEquals(d.get(k), expected_values[d.item_code][i])
|
||||
|
||||
def test_item_wise_tax_breakup(self):
|
||||
si = create_sales_invoice(qty=100, rate=50, do_not_save=True)
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"description": "Service Tax",
|
||||
"rate": 10
|
||||
})
|
||||
si.insert()
|
||||
|
||||
tax_breakup_html = '''\n<div class="tax-break-up" style="overflow-x: auto;">\n\t<table class="table table-bordered table-hover">\n\t\t<thead><tr><th class="text-left" style="min-width: 120px;">Item Name</th>\n<th class="text-right" style="min-width: 80px;">Taxable Amount</th>\n<th class="text-right" style="min-width: 80px;">_Test Account Service Tax - _TC</th></tr></thead>\n\t\t<tbody><tr><td>_Test Item</td><td class="text-right">\u20b9 5,000.00</td><td class="text-right">(10.0%) \u20b9 500.00</td></tr></tbody>\n\t</table>\n</div>'''
|
||||
|
||||
self.assertEqual(si.other_charges_calculation, tax_breakup_html)
|
||||
|
||||
|
||||
def create_sales_invoice(**args):
|
||||
si = frappe.new_doc("Sales Invoice")
|
||||
args = frappe._dict(args)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
@@ -2165,7 +2166,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-05-10 17:14:42.681757",
|
||||
"modified": "2017-07-06 17:54:03.347700",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
||||
@@ -576,11 +576,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
})
|
||||
|
||||
$(this.numeric_keypad).find('.numeric-del').click(function(){
|
||||
me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
|
||||
me.numeric_val = cstr(flt(me.selected_field.val())).slice(0, -1);
|
||||
me.selected_field.val(me.numeric_val);
|
||||
me.selected_field.trigger("change")
|
||||
// me.render_selected_item()
|
||||
if(me.numeric_id) {
|
||||
me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
|
||||
me.numeric_val = cstr(flt(me.selected_field.val())).slice(0, -1);
|
||||
me.selected_field.val(me.numeric_val);
|
||||
me.selected_field.trigger("change")
|
||||
} else {
|
||||
//Remove an item from the cart, if focus is at selected item
|
||||
me.remove_selected_item()
|
||||
}
|
||||
})
|
||||
|
||||
$(this.numeric_keypad).find('.pos-pay').click(function(){
|
||||
@@ -591,6 +595,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
})
|
||||
},
|
||||
|
||||
remove_selected_item: function() {
|
||||
this.remove_item = []
|
||||
idx = $(this.wrapper).find(".pos-selected-item-action").attr("data-idx")
|
||||
this.remove_item.push(idx)
|
||||
this.remove_zero_qty_item()
|
||||
this.update_paid_amount_status(false)
|
||||
},
|
||||
|
||||
render_list_customers: function () {
|
||||
var me = this;
|
||||
|
||||
@@ -1484,7 +1496,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
print_dialog: function () {
|
||||
var me = this;
|
||||
|
||||
this.frappe.msgprint = frappe.msgprint(
|
||||
this.msgprint = frappe.msgprint(
|
||||
`<a class="btn btn-primary print_doc"
|
||||
style="margin-right: 5px;">${__('Print')}</a>
|
||||
<a class="btn btn-default new_doc">${__('New')}</a>`);
|
||||
@@ -1495,7 +1507,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
})
|
||||
|
||||
$('.new_doc').click(function () {
|
||||
me.frappe.msgprint.hide()
|
||||
me.msgprint.hide()
|
||||
me.make_new_cart()
|
||||
})
|
||||
},
|
||||
|
||||
@@ -7,11 +7,12 @@ import frappe
|
||||
import datetime
|
||||
from frappe import _, msgprint, scrub
|
||||
from frappe.defaults import get_user_permissions
|
||||
from frappe.model.utils import get_fetch_values
|
||||
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, \
|
||||
add_years, get_timestamp, nowdate, flt
|
||||
from frappe.contacts.doctype.address.address import get_address_display, get_default_address
|
||||
from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact
|
||||
from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency
|
||||
from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext import get_default_currency
|
||||
|
||||
@@ -42,7 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
||||
|
||||
party = frappe.get_doc(party_type, party)
|
||||
|
||||
set_address_details(out, party, party_type)
|
||||
set_address_details(out, party, party_type, doctype, company)
|
||||
set_contact_details(out, party, party_type)
|
||||
set_other_values(out, party, party_type)
|
||||
set_price_list(out, party, party_type, price_list)
|
||||
@@ -60,10 +61,11 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
||||
|
||||
return out
|
||||
|
||||
def set_address_details(out, party, party_type):
|
||||
def set_address_details(out, party, party_type, doctype=None, company=None):
|
||||
billing_address_field = "customer_address" if party_type == "Lead" \
|
||||
else party_type.lower() + "_address"
|
||||
out[billing_address_field] = get_default_address(party_type, party.name)
|
||||
out.update(get_fetch_values(doctype, billing_address_field, out[billing_address_field]))
|
||||
|
||||
# address display
|
||||
out.address_display = get_address_display(out[billing_address_field])
|
||||
@@ -72,6 +74,11 @@ def set_address_details(out, party, party_type):
|
||||
if party_type in ["Customer", "Lead"]:
|
||||
out.shipping_address_name = get_default_address(party_type, party.name, 'is_shipping_address')
|
||||
out.shipping_address = get_address_display(out["shipping_address_name"])
|
||||
out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name))
|
||||
|
||||
if doctype and doctype in ['Sales Invoice']:
|
||||
out.company_address = get_default_address('Company', company)
|
||||
out.update(get_fetch_values(doctype, 'company_address', out.company_address))
|
||||
|
||||
def set_contact_details(out, party, party_type):
|
||||
out.contact_person = get_default_contact(party_type, party.name)
|
||||
@@ -363,28 +370,28 @@ def get_timeline_data(doctype, name):
|
||||
out.update({ timestamp: count })
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_dashboard_info(party_type, party):
|
||||
current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True)
|
||||
company = frappe.db.get_default("company") or frappe.get_all("Company")[0].name
|
||||
party_account_currency = get_party_account_currency(party_type, party, company)
|
||||
company_default_currency = get_default_currency() \
|
||||
or frappe.db.get_value('Company', company, 'default_currency')
|
||||
|
||||
|
||||
if party_account_currency==company_default_currency:
|
||||
total_field = "base_grand_total"
|
||||
else:
|
||||
total_field = "grand_total"
|
||||
|
||||
|
||||
doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice"
|
||||
|
||||
|
||||
billing_this_year = frappe.db.sql("""
|
||||
select sum({0})
|
||||
from `tab{1}`
|
||||
where {2}=%s and docstatus=1 and posting_date between %s and %s
|
||||
""".format(total_field, doctype, party_type.lower()),
|
||||
""".format(total_field, doctype, party_type.lower()),
|
||||
(party, current_fiscal_year.year_start_date, current_fiscal_year.year_end_date))
|
||||
|
||||
|
||||
total_unpaid = frappe.db.sql("""
|
||||
select sum(debit_in_account_currency) - sum(credit_in_account_currency)
|
||||
from `tabGL Entry`
|
||||
@@ -396,5 +403,5 @@ def get_dashboard_info(party_type, party):
|
||||
info["total_unpaid"] = flt(total_unpaid[0][0]) if total_unpaid else 0
|
||||
if party_type == "Supplier":
|
||||
info["total_unpaid"] = -1 * info["total_unpaid"]
|
||||
|
||||
|
||||
return info
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %}
|
||||
{% if(letterhead) { %}
|
||||
<div style="margin-bottom: 7px;" class="text-center">
|
||||
{%= frappe.boot.letter_heads[letterhead].header %}
|
||||
</div>
|
||||
{% } %}
|
||||
<h2 class="text-center">{%= __(report.report_name) %}</h2>
|
||||
<h4 class="text-center">{%= filters.customer || filters.supplier %} </h4>
|
||||
<h5 class="text-center">
|
||||
|
||||
@@ -10,7 +10,7 @@ from frappe.utils import (flt, getdate, get_first_day, get_last_day, date_diff,
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
|
||||
|
||||
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False,
|
||||
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False,
|
||||
company=None, reset_period_on_fy_change=True):
|
||||
"""Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
|
||||
Periodicity can be (Yearly, Quarterly, Monthly)"""
|
||||
@@ -85,8 +85,8 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_v
|
||||
return period_list
|
||||
|
||||
def get_fiscal_year_data(from_fiscal_year, to_fiscal_year):
|
||||
fiscal_year = frappe.db.sql("""select min(year_start_date) as year_start_date,
|
||||
max(year_end_date) as year_end_date from `tabFiscal Year` where
|
||||
fiscal_year = frappe.db.sql("""select min(year_start_date) as year_start_date,
|
||||
max(year_end_date) as year_end_date from `tabFiscal Year` where
|
||||
name between %(from_fiscal_year)s and %(to_fiscal_year)s""",
|
||||
{'from_fiscal_year': from_fiscal_year, 'to_fiscal_year': to_fiscal_year}, as_dict=1)
|
||||
|
||||
@@ -110,7 +110,7 @@ def get_label(periodicity, from_date, to_date):
|
||||
label = formatdate(from_date, "MMM YY") + "-" + formatdate(to_date, "MMM YY")
|
||||
|
||||
return label
|
||||
|
||||
|
||||
def get_data(company, root_type, balance_must_be, period_list, filters=None,
|
||||
accumulated_values=1, only_current_fiscal_year=True, ignore_closing_entries=False,
|
||||
ignore_accumulated_values_for_fy=False):
|
||||
@@ -119,16 +119,16 @@ def get_data(company, root_type, balance_must_be, period_list, filters=None,
|
||||
return None
|
||||
|
||||
accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
|
||||
|
||||
|
||||
company_currency = frappe.db.get_value("Company", company, "default_currency")
|
||||
|
||||
gl_entries_by_account = {}
|
||||
for root in frappe.db.sql("""select lft, rgt from tabAccount
|
||||
where root_type=%s and ifnull(parent_account, '') = ''""", root_type, as_dict=1):
|
||||
|
||||
set_gl_entries_by_account(company,
|
||||
|
||||
set_gl_entries_by_account(company,
|
||||
period_list[0]["year_start_date"] if only_current_fiscal_year else None,
|
||||
period_list[-1]["to_date"],
|
||||
period_list[-1]["to_date"],
|
||||
root.lft, root.rgt, filters,
|
||||
gl_entries_by_account, ignore_closing_entries=ignore_closing_entries)
|
||||
|
||||
@@ -136,7 +136,7 @@ def get_data(company, root_type, balance_must_be, period_list, filters=None,
|
||||
accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values)
|
||||
out = prepare_data(accounts, balance_must_be, period_list, company_currency)
|
||||
out = filter_out_zero_value_rows(out, parent_children_map)
|
||||
|
||||
|
||||
if out:
|
||||
add_total_row(out, root_type, balance_must_be, period_list, company_currency)
|
||||
|
||||
@@ -151,13 +151,13 @@ def calculate_values(accounts_by_name, gl_entries_by_account, period_list, accum
|
||||
|
||||
if entry.posting_date <= period.to_date:
|
||||
if (accumulated_values or entry.posting_date >= period.from_date) and \
|
||||
(not ignore_accumulated_values_for_fy or
|
||||
(not ignore_accumulated_values_for_fy or
|
||||
entry.fiscal_year == period.to_date_fiscal_year):
|
||||
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
|
||||
|
||||
if entry.posting_date < period_list[0].year_start_date:
|
||||
d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit)
|
||||
|
||||
|
||||
def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values):
|
||||
"""accumulate children's values in parent accounts"""
|
||||
for d in reversed(accounts):
|
||||
@@ -165,7 +165,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accu
|
||||
for period in period_list:
|
||||
accounts_by_name[d.parent_account][period.key] = \
|
||||
accounts_by_name[d.parent_account].get(period.key, 0.0) + d.get(period.key, 0.0)
|
||||
|
||||
|
||||
accounts_by_name[d.parent_account]["opening_balance"] = \
|
||||
accounts_by_name[d.parent_account].get("opening_balance", 0.0) + d.get("opening_balance", 0.0)
|
||||
|
||||
@@ -173,15 +173,15 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
|
||||
data = []
|
||||
year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d")
|
||||
year_end_date = period_list[-1]["year_end_date"].strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
for d in accounts:
|
||||
# add to output
|
||||
has_value = False
|
||||
total = 0
|
||||
row = frappe._dict({
|
||||
"account_name": d.account_name,
|
||||
"account": d.name,
|
||||
"parent_account": d.parent_account,
|
||||
"account_name": _(d.account_name),
|
||||
"account": _(d.name),
|
||||
"parent_account": _(d.parent_account),
|
||||
"indent": flt(d.indent),
|
||||
"year_start_date": year_start_date,
|
||||
"year_end_date": year_end_date,
|
||||
@@ -192,7 +192,7 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
|
||||
if d.get(period.key) and balance_must_be=="Credit":
|
||||
# change sign based on Debit or Credit, since calculation is done using (debit - credit)
|
||||
d[period.key] *= -1
|
||||
|
||||
|
||||
row[period.key] = flt(d.get(period.key, 0.0), 3)
|
||||
|
||||
if abs(row[period.key]) >= 0.005:
|
||||
@@ -203,9 +203,9 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
|
||||
row["has_value"] = has_value
|
||||
row["total"] = total
|
||||
data.append(row)
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False):
|
||||
data_with_value = []
|
||||
for d in data:
|
||||
@@ -224,8 +224,8 @@ def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False
|
||||
|
||||
def add_total_row(out, root_type, balance_must_be, period_list, company_currency):
|
||||
total_row = {
|
||||
"account_name": "'" + _("Total {0} ({1})").format(root_type, balance_must_be) + "'",
|
||||
"account": "'" + _("Total {0} ({1})").format(root_type, balance_must_be) + "'",
|
||||
"account_name": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
|
||||
"account": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
|
||||
"currency": company_currency
|
||||
}
|
||||
|
||||
@@ -235,11 +235,11 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
|
||||
total_row.setdefault(period.key, 0.0)
|
||||
total_row[period.key] += row.get(period.key, 0.0)
|
||||
row[period.key] = ""
|
||||
|
||||
|
||||
total_row.setdefault("total", 0.0)
|
||||
total_row["total"] += flt(row["total"])
|
||||
row["total"] = ""
|
||||
|
||||
|
||||
if total_row.has_key("total"):
|
||||
out.append(total_row)
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %}
|
||||
{% if(letterhead) { %}
|
||||
<div style="margin-bottom: 7px;" class="text-center">
|
||||
{%= frappe.boot.letter_heads[letterhead].header %}
|
||||
</div>
|
||||
{% } %}
|
||||
<h2 class="text-center">{%= __("Statement of Account") %}</h2>
|
||||
<h4 class="text-center">
|
||||
{% if (filters.party_name) { %}
|
||||
|
||||
@@ -75,7 +75,7 @@ frappe.query_reports["General Ledger"] = {
|
||||
}
|
||||
return party_type;
|
||||
},
|
||||
change: function() {
|
||||
on_change: function() {
|
||||
var party_type = frappe.query_report_filters_by_name.party_type.get_value();
|
||||
var party = frappe.query_report_filters_by_name.party.get_value();
|
||||
if(!party_type || !party) {
|
||||
|
||||
@@ -278,7 +278,7 @@ class GrossProfitGenerator(object):
|
||||
inner join `tabSales Invoice Item` on `tabSales Invoice Item`.parent = `tabSales Invoice`.name
|
||||
{sales_team_table}
|
||||
where
|
||||
`tabSales Invoice`.docstatus = 1 and `tabSales Invoice`.is_return != 1 {conditions} {match_cond}
|
||||
`tabSales Invoice`.docstatus = 1 {conditions} {match_cond}
|
||||
order by
|
||||
`tabSales Invoice`.posting_date desc, `tabSales Invoice`.posting_time desc"""
|
||||
.format(conditions=conditions, sales_person_cols=sales_person_cols,
|
||||
|
||||
@@ -7,11 +7,14 @@ from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
return _execute(filters)
|
||||
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
columns = get_columns()
|
||||
columns = get_columns(additional_table_columns)
|
||||
last_col = len(columns)
|
||||
|
||||
item_list = get_items(filters)
|
||||
item_list = get_items(filters, additional_query_columns)
|
||||
aii_account_map = get_aii_accounts()
|
||||
if item_list:
|
||||
item_row_tax, tax_accounts = get_tax_accounts(item_list, columns)
|
||||
@@ -23,7 +26,7 @@ def execute(filters=None):
|
||||
"width": 80
|
||||
})
|
||||
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
|
||||
|
||||
|
||||
data = []
|
||||
for d in item_list:
|
||||
purchase_receipt = None
|
||||
@@ -35,8 +38,16 @@ def execute(filters=None):
|
||||
|
||||
expense_account = d.expense_account or aii_account_map.get(d.company)
|
||||
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.supplier,
|
||||
d.supplier_name, d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
|
||||
purchase_receipt, expense_account, d.qty, d.base_net_rate, d.base_net_amount]
|
||||
d.supplier_name]
|
||||
|
||||
if additional_query_columns:
|
||||
for col in additional_query_columns:
|
||||
row.append(d.get(col))
|
||||
|
||||
row += [
|
||||
d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
|
||||
purchase_receipt, expense_account, d.qty, d.base_net_rate, d.base_net_amount
|
||||
]
|
||||
|
||||
for tax in tax_accounts:
|
||||
row.append(item_row_tax.get(d.name, {}).get(tax, 0))
|
||||
@@ -49,17 +60,27 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns():
|
||||
return [_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
||||
def get_columns(additional_table_columns):
|
||||
columns = [
|
||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
||||
_("Item Group") + ":Link/Item Group:100", _("Invoice") + ":Link/Purchase Invoice:120",
|
||||
_("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
|
||||
"Supplier Name::120", "Payable Account:Link/Account:120",
|
||||
"Supplier Name::120"
|
||||
]
|
||||
|
||||
if additional_table_columns:
|
||||
columns += additional_table_columns
|
||||
|
||||
columns += [
|
||||
"Payable Account:Link/Account:120",
|
||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
||||
_("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
|
||||
_("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
|
||||
_("Qty") + ":Float:120", _("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
|
||||
@@ -74,21 +95,23 @@ def get_conditions(filters):
|
||||
|
||||
return conditions
|
||||
|
||||
def get_items(filters):
|
||||
def get_items(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
match_conditions = frappe.build_match_conditions("Purchase Invoice")
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
select
|
||||
pi_item.name, pi_item.parent, pi.posting_date, pi.credit_to, pi.company,
|
||||
pi.supplier, pi.remarks, pi.base_net_total, pi_item.item_code, pi_item.item_name,
|
||||
pi_item.item_group, pi_item.project, pi_item.purchase_order, pi_item.purchase_receipt,
|
||||
pi_item.po_detail, pi_item.expense_account, pi_item.qty, pi_item.base_net_rate,
|
||||
pi_item.base_net_amount, pi.supplier_name, pi.mode_of_payment
|
||||
pi.supplier, pi.remarks, pi.base_net_total, pi_item.item_code, pi_item.item_name,
|
||||
pi_item.item_group, pi_item.project, pi_item.purchase_order, pi_item.purchase_receipt,
|
||||
pi_item.po_detail, pi_item.expense_account, pi_item.qty, pi_item.base_net_rate,
|
||||
pi_item.base_net_amount, pi.supplier_name, pi.mode_of_payment {0}
|
||||
from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
|
||||
where pi.name = pi_item.parent and pi.docstatus = 1 %s %s
|
||||
order by pi.posting_date desc, pi_item.item_code desc
|
||||
""" % (conditions, match_conditions), filters, as_dict=1)
|
||||
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
|
||||
|
||||
def get_aii_accounts():
|
||||
return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany"))
|
||||
@@ -104,11 +127,11 @@ def get_tax_accounts(item_list, columns):
|
||||
item_row_map.setdefault(d.parent, {}).setdefault(d.item_code, []).append(d)
|
||||
|
||||
tax_details = frappe.db.sql("""
|
||||
select
|
||||
select
|
||||
parent, account_head, item_wise_tax_detail, charge_type, base_tax_amount_after_discount_amount
|
||||
from `tabPurchase Taxes and Charges`
|
||||
where parenttype = 'Purchase Invoice' and docstatus = 1
|
||||
and (account_head is not null and account_head != '')
|
||||
from `tabPurchase Taxes and Charges`
|
||||
where parenttype = 'Purchase Invoice' and docstatus = 1
|
||||
and (account_head is not null and account_head != '')
|
||||
and category in ('Total', 'Valuation and Total')
|
||||
and parent in (%s)
|
||||
""" % ', '.join(['%s']*len(invoice_item_row)), tuple(invoice_item_row.keys()))
|
||||
@@ -120,17 +143,17 @@ def get_tax_accounts(item_list, columns):
|
||||
if item_wise_tax_detail:
|
||||
try:
|
||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
||||
|
||||
|
||||
for item_code, tax_amount in item_wise_tax_detail.items():
|
||||
tax_amount = flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount)
|
||||
|
||||
item_net_amount = sum([flt(d.base_net_amount)
|
||||
|
||||
item_net_amount = sum([flt(d.base_net_amount)
|
||||
for d in item_row_map.get(parent, {}).get(item_code, [])])
|
||||
|
||||
|
||||
for d in item_row_map.get(parent, {}).get(item_code, []):
|
||||
item_tax_amount = flt((tax_amount * d.base_net_amount) / item_net_amount) if item_net_amount else 0
|
||||
item_row_tax.setdefault(d.name, {})[account_head] = item_tax_amount
|
||||
|
||||
|
||||
except ValueError:
|
||||
continue
|
||||
elif charge_type == "Actual" and tax_amount:
|
||||
|
||||
@@ -8,11 +8,14 @@ from frappe.utils import flt
|
||||
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
||||
|
||||
def execute(filters=None):
|
||||
return _execute(filters)
|
||||
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
columns = get_columns()
|
||||
columns = get_columns(additional_table_columns)
|
||||
last_col = len(columns)
|
||||
|
||||
item_list = get_items(filters)
|
||||
item_list = get_items(filters, additional_query_columns)
|
||||
if item_list:
|
||||
item_row_tax, tax_accounts = get_tax_accounts(item_list, columns)
|
||||
columns.append({
|
||||
@@ -21,7 +24,7 @@ def execute(filters=None):
|
||||
"fieldtype": "Data",
|
||||
"width": 80
|
||||
})
|
||||
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
|
||||
company_currency = frappe.db.get_value("Company", filters.get("company"), "default_currency")
|
||||
mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list]))
|
||||
|
||||
data = []
|
||||
@@ -35,10 +38,17 @@ def execute(filters=None):
|
||||
if not delivery_note and d.update_stock:
|
||||
delivery_note = d.parent
|
||||
|
||||
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.customer, d.customer_name,
|
||||
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
|
||||
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.customer, d.customer_name]
|
||||
|
||||
if additional_query_columns:
|
||||
for col in additional_query_columns:
|
||||
row.append(d.get(col))
|
||||
|
||||
row += [
|
||||
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
|
||||
d.territory, d.project, d.company, d.sales_order,
|
||||
delivery_note, d.income_account, d.cost_center, d.qty, d.base_net_rate, d.base_net_amount]
|
||||
delivery_note, d.income_account, d.cost_center, d.qty, d.base_net_rate, d.base_net_amount
|
||||
]
|
||||
|
||||
for tax in tax_accounts:
|
||||
row.append(item_row_tax.get(d.name, {}).get(tax, 0))
|
||||
@@ -50,12 +60,18 @@ def execute(filters=None):
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
def get_columns(additional_table_columns):
|
||||
columns = [
|
||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
||||
_("Item Group") + ":Link/Item Group:100", _("Invoice") + ":Link/Sales Invoice:120",
|
||||
_("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
|
||||
_("Customer Name") + "::120", _("Customer Group") + ":Link/Customer Group:120",
|
||||
_("Customer Name") + "::120"]
|
||||
|
||||
if additional_table_columns:
|
||||
columns += additional_table_columns
|
||||
|
||||
columns += [
|
||||
_("Customer Group") + ":Link/Customer Group:120",
|
||||
_("Receivable Account") + ":Link/Account:120",
|
||||
_("Mode of Payment") + "::120", _("Territory") + ":Link/Territory:80",
|
||||
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
|
||||
@@ -66,6 +82,8 @@ def get_columns():
|
||||
_("Amount") + ":Currency/currency:120"
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
|
||||
@@ -76,15 +94,18 @@ def get_conditions(filters):
|
||||
("to_date", " and si.posting_date<=%(to_date)s")):
|
||||
if filters.get(opts[0]):
|
||||
conditions += opts[1]
|
||||
|
||||
|
||||
if filters.get("mode_of_payment"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Payment`
|
||||
where parent=si.name
|
||||
where parent=si.name
|
||||
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
||||
|
||||
return conditions
|
||||
|
||||
def get_items(filters):
|
||||
def get_items(filters, additional_query_columns):
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
@@ -93,10 +114,11 @@ def get_items(filters):
|
||||
si_item.item_code, si_item.item_name, si_item.item_group, si_item.sales_order,
|
||||
si_item.delivery_note, si_item.income_account, si_item.cost_center, si_item.qty,
|
||||
si_item.base_net_rate, si_item.base_net_amount, si.customer_name,
|
||||
si.customer_group, si_item.so_detail, si.update_stock
|
||||
si.customer_group, si_item.so_detail, si.update_stock {0}
|
||||
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
|
||||
where si.name = si_item.parent and si.docstatus = 1 %s
|
||||
order by si.posting_date desc, si_item.item_code desc""" % conditions, filters, as_dict=1)
|
||||
order by si.posting_date desc, si_item.item_code desc
|
||||
""".format(additional_query_columns or '') % conditions, filters, as_dict=1)
|
||||
|
||||
def get_tax_accounts(item_list, columns):
|
||||
import json
|
||||
|
||||
@@ -7,10 +7,13 @@ from frappe.utils import flt
|
||||
from frappe import msgprint, _
|
||||
|
||||
def execute(filters=None):
|
||||
return _execute(filters)
|
||||
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
invoice_list = get_invoices(filters)
|
||||
columns, expense_accounts, tax_accounts = get_columns(invoice_list)
|
||||
invoice_list = get_invoices(filters, additional_query_columns)
|
||||
columns, expense_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns)
|
||||
|
||||
if not invoice_list:
|
||||
msgprint(_("No record found"))
|
||||
@@ -20,8 +23,9 @@ def execute(filters=None):
|
||||
invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
|
||||
invoice_expense_map, expense_accounts)
|
||||
invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
|
||||
supplier_details = get_supplier_details(invoice_list)
|
||||
|
||||
suppliers = list(set([d.supplier for d in invoice_list]))
|
||||
supplier_details = get_supplier_details(suppliers)
|
||||
|
||||
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
|
||||
|
||||
data = []
|
||||
@@ -31,10 +35,18 @@ def execute(filters=None):
|
||||
purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])))
|
||||
project = list(set(invoice_po_pr_map.get(inv.name, {}).get("project", [])))
|
||||
|
||||
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name,
|
||||
supplier_details.get(inv.supplier),
|
||||
inv.credit_to, inv.mode_of_payment, ", ".join(project), inv.bill_no, inv.bill_date, inv.remarks,
|
||||
", ".join(purchase_order), ", ".join(purchase_receipt), company_currency]
|
||||
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name]
|
||||
|
||||
if additional_query_columns:
|
||||
for col in additional_query_columns:
|
||||
row.append(inv.get(col))
|
||||
|
||||
row += [
|
||||
supplier_details.get(inv.supplier), # supplier_type
|
||||
inv.credit_to, inv.mode_of_payment, ", ".join(project),
|
||||
inv.bill_no, inv.bill_date, inv.remarks,
|
||||
", ".join(purchase_order), ", ".join(purchase_receipt), company_currency
|
||||
]
|
||||
|
||||
# map expense values
|
||||
base_net_total = 0
|
||||
@@ -61,15 +73,20 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns(invoice_list):
|
||||
def get_columns(invoice_list, additional_table_columns):
|
||||
"""return columns based on filters"""
|
||||
columns = [
|
||||
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80",
|
||||
_("Supplier Id") + "::120", _("Supplier Name") + "::120",
|
||||
_("Supplier Type") + ":Link/Supplier Type:120", _("Payable Account") + ":Link/Account:120",
|
||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
||||
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80",
|
||||
_("Supplier Id") + "::120", _("Supplier Name") + "::120"]
|
||||
|
||||
if additional_table_columns:
|
||||
columns += additional_table_columns
|
||||
|
||||
columns += [
|
||||
_("Supplier Type") + ":Link/Supplier Type:120", _("Payable Account") + ":Link/Account:120",
|
||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
||||
_("Bill No") + "::120", _("Bill Date") + ":Date:80", _("Remarks") + "::150",
|
||||
_("Purchase Order") + ":Link/Purchase Order:100",
|
||||
_("Purchase Order") + ":Link/Purchase Order:100",
|
||||
_("Purchase Receipt") + ":Link/Purchase Receipt:100",
|
||||
{
|
||||
"fieldname": "currency",
|
||||
@@ -114,27 +131,31 @@ def get_conditions(filters):
|
||||
|
||||
if filters.get("from_date"): conditions += " and posting_date>=%(from_date)s"
|
||||
if filters.get("to_date"): conditions += " and posting_date<=%(to_date)s"
|
||||
|
||||
|
||||
if filters.get("mode_of_payment"): conditions += " and ifnull(mode_of_payment, '') = %(mode_of_payment)s"
|
||||
|
||||
return conditions
|
||||
|
||||
def get_invoices(filters):
|
||||
def get_invoices(filters, additional_query_columns):
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
|
||||
conditions = get_conditions(filters)
|
||||
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, mode_of_payment
|
||||
from `tabPurchase Invoice`
|
||||
select
|
||||
name, posting_date, credit_to, supplier, supplier_name, bill_no, bill_date,
|
||||
remarks, base_net_total, base_grand_total, outstanding_amount,
|
||||
mode_of_payment {0}
|
||||
from `tabPurchase Invoice`
|
||||
where docstatus = 1 %s
|
||||
order by posting_date desc, name desc""" % conditions, filters, as_dict=1)
|
||||
order by posting_date desc, name desc""".format(additional_query_columns or '') % conditions, filters, as_dict=1)
|
||||
|
||||
|
||||
def get_invoice_expense_map(invoice_list):
|
||||
expense_details = frappe.db.sql("""
|
||||
select parent, expense_account, sum(base_net_amount) as amount
|
||||
from `tabPurchase Invoice Item`
|
||||
where parent in (%s)
|
||||
from `tabPurchase Invoice Item`
|
||||
where parent in (%s)
|
||||
group by parent, expense_account
|
||||
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
|
||||
|
||||
@@ -149,7 +170,7 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
|
||||
tax_details = frappe.db.sql("""
|
||||
select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount)
|
||||
else sum(base_tax_amount_after_discount_amount) * -1 end as tax_amount
|
||||
from `tabPurchase Taxes and Charges`
|
||||
from `tabPurchase Taxes and Charges`
|
||||
where parent in (%s) and category in ('Total', 'Valuation and Total')
|
||||
group by parent, account_head, add_deduct_tax
|
||||
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
|
||||
@@ -169,8 +190,8 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
|
||||
|
||||
def get_invoice_po_pr_map(invoice_list):
|
||||
pi_items = frappe.db.sql("""
|
||||
select parent, purchase_order, purchase_receipt, po_detail, project
|
||||
from `tabPurchase Invoice Item`
|
||||
select parent, purchase_order, purchase_receipt, po_detail, project
|
||||
from `tabPurchase Invoice Item`
|
||||
where parent in (%s) and (ifnull(purchase_order, '') != '' or ifnull(purchase_receipt, '') != '')
|
||||
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
|
||||
|
||||
@@ -205,9 +226,8 @@ def get_account_details(invoice_list):
|
||||
|
||||
return account_map
|
||||
|
||||
def get_supplier_details(invoice_list):
|
||||
def get_supplier_details(suppliers):
|
||||
supplier_details = {}
|
||||
suppliers = list(set([inv.supplier for inv in invoice_list]))
|
||||
for supp in frappe.db.sql("""select name, supplier_type from `tabSupplier`
|
||||
where name in (%s)""" % ", ".join(["%s"]*len(suppliers)), tuple(suppliers), as_dict=1):
|
||||
supplier_details.setdefault(supp.name, supp.supplier_type)
|
||||
|
||||
@@ -7,10 +7,13 @@ from frappe.utils import flt
|
||||
from frappe import msgprint, _
|
||||
|
||||
def execute(filters=None):
|
||||
return _execute(filters)
|
||||
|
||||
def _execute(filters, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = frappe._dict({})
|
||||
|
||||
invoice_list = get_invoices(filters)
|
||||
columns, income_accounts, tax_accounts = get_columns(invoice_list)
|
||||
invoice_list = get_invoices(filters, additional_query_columns)
|
||||
columns, income_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns)
|
||||
|
||||
if not invoice_list:
|
||||
msgprint(_("No record found"))
|
||||
@@ -21,8 +24,9 @@ def execute(filters=None):
|
||||
invoice_income_map, income_accounts)
|
||||
|
||||
invoice_so_dn_map = get_invoice_so_dn_map(invoice_list)
|
||||
customer_map = get_customer_details(invoice_list)
|
||||
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
|
||||
customers = list(set([inv.customer for inv in invoice_list]))
|
||||
customer_map = get_customer_details(customers)
|
||||
company_currency = frappe.db.get_value("Company", filters.get("company"), "default_currency")
|
||||
mode_of_payments = get_mode_of_payments([inv.name for inv in invoice_list])
|
||||
|
||||
data = []
|
||||
@@ -31,12 +35,22 @@ def execute(filters=None):
|
||||
sales_order = list(set(invoice_so_dn_map.get(inv.name, {}).get("sales_order", [])))
|
||||
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, {}).get("customer_group"),
|
||||
customer_map.get(inv.customer, {}).get("territory"),
|
||||
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])), inv.project, inv.remarks,
|
||||
", ".join(sales_order), ", ".join(delivery_note), company_currency]
|
||||
customer_details = customer_map.get(inv.customer, {})
|
||||
row = [
|
||||
inv.name, inv.posting_date, inv.customer, inv.customer_name
|
||||
]
|
||||
|
||||
if additional_query_columns:
|
||||
for col in additional_query_columns:
|
||||
row.append(inv.get(col))
|
||||
|
||||
row +=[
|
||||
customer_details.get("customer_group"),
|
||||
customer_details.get("territory"),
|
||||
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])),
|
||||
inv.project, inv.remarks,
|
||||
", ".join(sales_order), ", ".join(delivery_note), company_currency
|
||||
]
|
||||
# map income values
|
||||
base_net_total = 0
|
||||
for income_acc in income_accounts:
|
||||
@@ -62,15 +76,20 @@ def execute(filters=None):
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns(invoice_list):
|
||||
def get_columns(invoice_list, additional_table_columns):
|
||||
"""return columns based on filters"""
|
||||
columns = [
|
||||
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80",
|
||||
_("Customer Id") + "::120", _("Customer Name") + "::120",
|
||||
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
|
||||
_("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
|
||||
_("Project") +":Link/Project:80", _("Remarks") + "::150",
|
||||
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80",
|
||||
_("Customer") + ":Link/Customer:120", _("Customer Name") + "::120"
|
||||
]
|
||||
|
||||
if additional_table_columns:
|
||||
columns += additional_table_columns
|
||||
|
||||
columns +=[
|
||||
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
|
||||
_("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
|
||||
_("Project") +":Link/Project:80", _("Remarks") + "::150",
|
||||
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
|
||||
{
|
||||
"fieldname": "currency",
|
||||
@@ -113,20 +132,23 @@ def get_conditions(filters):
|
||||
|
||||
if filters.get("from_date"): conditions += " and posting_date >= %(from_date)s"
|
||||
if filters.get("to_date"): conditions += " and posting_date <= %(to_date)s"
|
||||
|
||||
|
||||
if filters.get("mode_of_payment"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Payment`
|
||||
where parent=`tabSales Invoice`.name
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
||||
|
||||
|
||||
return conditions
|
||||
|
||||
def get_invoices(filters):
|
||||
def get_invoices(filters, additional_query_columns):
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""select name, posting_date, debit_to, project, customer, customer_name, remarks,
|
||||
base_net_total, base_grand_total, base_rounded_total, outstanding_amount
|
||||
return frappe.db.sql("""select name, posting_date, debit_to, project, customer, customer_name, remarks,
|
||||
base_net_total, base_grand_total, base_rounded_total, outstanding_amount {0}
|
||||
from `tabSales Invoice`
|
||||
where docstatus = 1 %s order by posting_date desc, name desc""" %
|
||||
where docstatus = 1 %s order by posting_date desc, name desc""".format(additional_query_columns or '') %
|
||||
conditions, filters, as_dict=1)
|
||||
|
||||
def get_invoice_income_map(invoice_list):
|
||||
@@ -184,9 +206,8 @@ def get_invoice_so_dn_map(invoice_list):
|
||||
|
||||
return invoice_so_dn_map
|
||||
|
||||
def get_customer_details(invoice_list):
|
||||
def get_customer_details(customers):
|
||||
customer_map = {}
|
||||
customers = list(set([inv.customer for inv in invoice_list]))
|
||||
for cust in frappe.db.sql("""select name, territory, customer_group from `tabCustomer`
|
||||
where name in (%s)""" % ", ".join(["%s"]*len(customers)), tuple(customers), as_dict=1):
|
||||
customer_map.setdefault(cust.name, cust)
|
||||
|
||||
@@ -270,6 +270,9 @@ def make_purchase_receipt(source_name, target_doc=None):
|
||||
doc = get_mapped_doc("Purchase Order", source_name, {
|
||||
"Purchase Order": {
|
||||
"doctype": "Purchase Receipt",
|
||||
"field_map": {
|
||||
"per_billed": "per_billed"
|
||||
},
|
||||
"validation": {
|
||||
"docstatus": ["=", 1],
|
||||
}
|
||||
@@ -311,6 +314,9 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
doc = get_mapped_doc("Purchase Order", source_name, {
|
||||
"Purchase Order": {
|
||||
"doctype": "Purchase Invoice",
|
||||
"field_map": {
|
||||
"party_account_currency": "party_account_currency"
|
||||
},
|
||||
"validation": {
|
||||
"docstatus": ["=", 1],
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||
from frappe.utils import nowdate
|
||||
|
||||
class TestRequestforQuotation(unittest.TestCase):
|
||||
@@ -28,6 +30,31 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
self.assertEquals(sq1.get('items')[0].item_code, "_Test Item")
|
||||
self.assertEquals(sq1.get('items')[0].qty, 5)
|
||||
|
||||
def test_make_supplier_quotation_with_special_characters(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||
|
||||
frappe.delete_doc_if_exists("Supplier", "_Test Supplier '1", force=1)
|
||||
supplier = frappe.new_doc("Supplier")
|
||||
supplier.supplier_name = "_Test Supplier '1"
|
||||
supplier.supplier_type = "_Test Supplier Type"
|
||||
supplier.insert()
|
||||
|
||||
rfq = make_request_for_quotation(supplier_wt_appos)
|
||||
|
||||
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
|
||||
sq.submit()
|
||||
|
||||
frappe.form_dict = frappe.local("form_dict")
|
||||
frappe.form_dict.name = rfq.name
|
||||
|
||||
self.assertEqual(
|
||||
check_supplier_has_docname_access(supplier_wt_appos[0].get('supplier')),
|
||||
True
|
||||
)
|
||||
|
||||
# reset form_dict
|
||||
frappe.form_dict.name = None
|
||||
|
||||
def test_make_supplier_quotation_from_portal(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||
rfq = make_request_for_quotation()
|
||||
@@ -44,8 +71,11 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
self.assertEquals(supplier_quotation_doc.get('items')[0].amount, 500)
|
||||
|
||||
|
||||
def make_request_for_quotation():
|
||||
supplier_data = get_supplier_data()
|
||||
def make_request_for_quotation(supplier_data=None):
|
||||
"""
|
||||
:param supplier_data: List containing supplier data
|
||||
"""
|
||||
supplier_data = supplier_data if supplier_data else get_supplier_data()
|
||||
rfq = frappe.new_doc('Request for Quotation')
|
||||
rfq.transaction_date = nowdate()
|
||||
rfq.status = 'Draft'
|
||||
@@ -77,3 +107,8 @@ def get_supplier_data():
|
||||
"supplier": "_Test Supplier 1",
|
||||
"supplier_name": "_Test Supplier 1"
|
||||
}]
|
||||
|
||||
supplier_wt_appos = [{
|
||||
"supplier": "_Test Supplier '1",
|
||||
"supplier_name": "_Test Supplier '1",
|
||||
}]
|
||||
|
||||
3
erpnext/buying/doctype/supplier/regional/india.js
Normal file
@@ -0,0 +1,3 @@
|
||||
{% include "erpnext/regional/india/party.js" %}
|
||||
|
||||
erpnext.setup_gst_reminder_button('Supplier');
|
||||
@@ -1,3 +1,3 @@
|
||||
frappe.listview_settings['Supplier'] = {
|
||||
add_fields: ["supplier_name", "supplier_type"],
|
||||
add_fields: ["supplier_name", "supplier_type", "image"],
|
||||
};
|
||||
|
||||
8
erpnext/change_log/v8/v8_3_0.md
Normal file
@@ -0,0 +1,8 @@
|
||||
### Production Order Enahancement
|
||||
- Show required items child table.
|
||||
- Source warehouse for each Raw Materials, in Production Order Item and BOM Item table.
|
||||
- Group warehouse allowed for Source and WIP warehouse.
|
||||
### GST Tax Invoice Print Format
|
||||
- Added print format to show tax(GST) breakup.
|
||||
- Total Stock Summary report.
|
||||
- Include Search Fields in Customer Query.
|
||||
@@ -35,7 +35,7 @@ def get_data():
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Accounts Receivable",
|
||||
"doctype": "Sales Invoice",
|
||||
"doctype": "Sales Invoice",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
@@ -198,6 +198,39 @@ def get_data():
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Goods and Services Tax (GST India)"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "GST Settings",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "GST HSN Code",
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GST Sales Register",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GST Purchase Register",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GST Itemised Sales Register",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GST Itemised Purchase Register",
|
||||
"is_query_report": True
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Budget and Cost Center"),
|
||||
"items": [
|
||||
|
||||
@@ -137,7 +137,14 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Assessment Result Tool"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Course wise Assessment Report",
|
||||
"doctype": "Assessment Result"
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -49,6 +49,12 @@ def get_data():
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Support Hours",
|
||||
"doctype": "Issue",
|
||||
"is_query_report": True
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
|
||||
@@ -255,7 +255,7 @@ class BuyingController(StockController):
|
||||
|
||||
def get_items_from_bom(self, item_code, bom):
|
||||
bom_items = frappe.db.sql("""select t2.item_code,
|
||||
t2.qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit,
|
||||
t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit,
|
||||
t2.rate, t2.stock_uom, t2.name, t2.description
|
||||
from `tabBOM` t1, `tabBOM Item` t2, tabItem t3
|
||||
where t2.parent = t1.name and t1.item = %s
|
||||
|
||||
@@ -169,6 +169,7 @@ def create_variant(item, args):
|
||||
|
||||
return variant
|
||||
|
||||
|
||||
def copy_attributes_to_variant(item, variant):
|
||||
from frappe.model import no_value_fields
|
||||
|
||||
@@ -181,8 +182,9 @@ def copy_attributes_to_variant(item, variant):
|
||||
exclude_fields += ['manufacturer', 'manufacturer_part_no']
|
||||
|
||||
for field in item.meta.fields:
|
||||
if field.fieldtype not in no_value_fields and (not field.no_copy)\
|
||||
and field.fieldname not in exclude_fields:
|
||||
# "Table" is part of `no_value_field` but we shouldn't ignore tables
|
||||
if (field.fieldtype == 'Table' or field.fieldtype not in no_value_fields) \
|
||||
and (not field.no_copy) and field.fieldname not in exclude_fields:
|
||||
if variant.get(field.fieldname) != item.get(field.fieldname):
|
||||
variant.set(field.fieldname, item.get(field.fieldname))
|
||||
variant.variant_of = item.name
|
||||
|
||||
@@ -68,14 +68,17 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
fields = ["name", "customer_name", "customer_group", "territory"]
|
||||
|
||||
meta = frappe.get_meta("Customer")
|
||||
fields = fields + [f for f in meta.get_search_fields() if not f in fields]
|
||||
searchfields = meta.get_search_fields()
|
||||
searchfields = searchfields + [f for f in [searchfield or "name", "customer_name"] \
|
||||
if not f in searchfields]
|
||||
fields = fields + [f for f in searchfields if not f in fields]
|
||||
|
||||
fields = ", ".join(fields)
|
||||
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||
|
||||
return frappe.db.sql("""select {fields} from `tabCustomer`
|
||||
where docstatus < 2
|
||||
and ({key} like %(txt)s
|
||||
or customer_name like %(txt)s) and disabled=0
|
||||
and ({scond}) and disabled=0
|
||||
{mcond}
|
||||
order by
|
||||
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||
@@ -84,7 +87,7 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
name, customer_name
|
||||
limit %(start)s, %(page_len)s""".format(**{
|
||||
"fields": fields,
|
||||
"key": searchfield,
|
||||
"scond": searchfields,
|
||||
"mcond": get_match_cond(doctype)
|
||||
}), {
|
||||
'txt': "%%%s%%" % txt,
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import json
|
||||
import frappe, erpnext
|
||||
from frappe import _, scrub
|
||||
from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction
|
||||
from frappe.utils import cint, flt, cstr, fmt_money, round_based_on_smallest_currency_fraction
|
||||
from erpnext.controllers.accounts_controller import validate_conversion_rate, \
|
||||
validate_taxes_and_charges, validate_inclusive_tax
|
||||
|
||||
@@ -24,6 +24,9 @@ class calculate_taxes_and_totals(object):
|
||||
|
||||
if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||
self.calculate_total_advance()
|
||||
|
||||
if self.doc.meta.get_field("other_charges_calculation"):
|
||||
self.set_item_wise_tax_breakup()
|
||||
|
||||
def _calculate(self):
|
||||
self.calculate_item_values()
|
||||
@@ -504,3 +507,105 @@ class calculate_taxes_and_totals(object):
|
||||
rate_with_margin = flt(item.price_list_rate) + flt(margin_value)
|
||||
|
||||
return rate_with_margin
|
||||
|
||||
def set_item_wise_tax_breakup(self):
|
||||
item_tax = {}
|
||||
tax_accounts = []
|
||||
company_currency = erpnext.get_company_currency(self.doc.company)
|
||||
|
||||
item_tax, tax_accounts = self.get_item_tax(item_tax, tax_accounts, company_currency)
|
||||
|
||||
headings = get_table_column_headings(tax_accounts)
|
||||
|
||||
distinct_items = self.get_distinct_items()
|
||||
|
||||
rows = get_table_rows(distinct_items, item_tax, tax_accounts, company_currency)
|
||||
|
||||
if not rows:
|
||||
self.doc.other_charges_calculation = ""
|
||||
else:
|
||||
self.doc.other_charges_calculation = '''
|
||||
<div class="tax-break-up" style="overflow-x: auto;">
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead><tr>{headings}</tr></thead>
|
||||
<tbody>{rows}</tbody>
|
||||
</table>
|
||||
</div>'''.format(**{
|
||||
"headings": "\n".join(headings),
|
||||
"rows": "\n".join(rows)
|
||||
})
|
||||
|
||||
def get_item_tax(self, item_tax, tax_accounts, company_currency):
|
||||
for tax in self.doc.taxes:
|
||||
tax_amount_precision = tax.precision("tax_amount")
|
||||
tax_rate_precision = tax.precision("rate");
|
||||
|
||||
item_tax_map = self._load_item_tax_rate(tax.item_wise_tax_detail)
|
||||
for item_code, tax_data in item_tax_map.items():
|
||||
if not item_tax.get(item_code):
|
||||
item_tax[item_code] = {}
|
||||
|
||||
if isinstance(tax_data, list):
|
||||
tax_rate = ""
|
||||
if tax_data[0]:
|
||||
if tax.charge_type == "Actual":
|
||||
tax_rate = fmt_money(flt(tax_data[0], tax_amount_precision),
|
||||
tax_amount_precision, company_currency)
|
||||
else:
|
||||
tax_rate = cstr(flt(tax_data[0], tax_rate_precision)) + "%"
|
||||
|
||||
tax_amount = fmt_money(flt(tax_data[1], tax_amount_precision),
|
||||
tax_amount_precision, company_currency)
|
||||
|
||||
item_tax[item_code][tax.name] = [tax_rate, tax_amount]
|
||||
else:
|
||||
item_tax[item_code][tax.name] = [cstr(flt(tax_data, tax_rate_precision)) + "%", ""]
|
||||
tax_accounts.append([tax.name, tax.account_head])
|
||||
|
||||
return item_tax, tax_accounts
|
||||
|
||||
|
||||
def get_distinct_items(self):
|
||||
distinct_item_names = []
|
||||
distinct_items = []
|
||||
for item in self.doc.items:
|
||||
item_code = item.item_code or item.item_name
|
||||
if item_code not in distinct_item_names:
|
||||
distinct_item_names.append(item_code)
|
||||
distinct_items.append(item)
|
||||
|
||||
return distinct_items
|
||||
|
||||
def get_table_column_headings(tax_accounts):
|
||||
headings_name = [_("Item Name"), _("Taxable Amount")] + [d[1] for d in tax_accounts]
|
||||
headings = []
|
||||
for head in headings_name:
|
||||
if head == _("Item Name"):
|
||||
headings.append('<th style="min-width: 120px;" class="text-left">' + (head or "") + "</th>")
|
||||
else:
|
||||
headings.append('<th style="min-width: 80px;" class="text-right">' + (head or "") + "</th>")
|
||||
|
||||
return headings
|
||||
|
||||
def get_table_rows(distinct_items, item_tax, tax_accounts, company_currency):
|
||||
rows = []
|
||||
for item in distinct_items:
|
||||
item_tax_record = item_tax.get(item.item_code or item.item_name)
|
||||
if not item_tax_record:
|
||||
continue
|
||||
|
||||
taxes = []
|
||||
for head in tax_accounts:
|
||||
if item_tax_record[head[0]]:
|
||||
taxes.append("<td class='text-right'>(" + item_tax_record[head[0]][0] + ") "
|
||||
+ item_tax_record[head[0]][1] + "</td>")
|
||||
else:
|
||||
taxes.append("<td></td>")
|
||||
|
||||
rows.append("<tr><td>{item_name}</td><td class='text-right'>{taxable_amount}</td>{taxes}</tr>".format(**{
|
||||
"item_name": item.item_name,
|
||||
"taxable_amount": fmt_money(item.net_amount, item.precision("net_amount"), company_currency),
|
||||
"taxes": "\n".join(taxes)
|
||||
}))
|
||||
|
||||
return rows
|
||||
58
erpnext/controllers/tests/test_item_variant.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import json
|
||||
import unittest
|
||||
|
||||
from erpnext.controllers.item_variant import copy_attributes_to_variant, make_variant_item_code
|
||||
|
||||
# python 3 compatibility stuff
|
||||
try:
|
||||
unicode = unicode
|
||||
except NameError:
|
||||
# Python 3
|
||||
basestring = (str, bytes)
|
||||
else:
|
||||
# Python 2
|
||||
basestring = basestring
|
||||
|
||||
|
||||
def create_variant_with_tables(item, args):
|
||||
if isinstance(args, basestring):
|
||||
args = json.loads(args)
|
||||
|
||||
template = frappe.get_doc("Item", item)
|
||||
template.quality_parameters.append({
|
||||
"specification": "Moisture",
|
||||
"value": "< 5%",
|
||||
})
|
||||
variant = frappe.new_doc("Item")
|
||||
variant.variant_based_on = 'Item Attribute'
|
||||
variant_attributes = []
|
||||
|
||||
for d in template.attributes:
|
||||
variant_attributes.append({
|
||||
"attribute": d.attribute,
|
||||
"attribute_value": args.get(d.attribute)
|
||||
})
|
||||
|
||||
variant.set("attributes", variant_attributes)
|
||||
copy_attributes_to_variant(template, variant)
|
||||
make_variant_item_code(template.item_code, template.item_name, variant)
|
||||
|
||||
return variant
|
||||
|
||||
|
||||
def make_item_variant():
|
||||
frappe.delete_doc_if_exists("Item", "_Test Variant Item-S", force=1)
|
||||
variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Small"}')
|
||||
variant.item_code = "_Test Variant Item-S"
|
||||
variant.item_name = "_Test Variant Item-S"
|
||||
variant.save()
|
||||
return variant
|
||||
|
||||
|
||||
class TestItemVariant(unittest.TestCase):
|
||||
def test_tables_in_template_copied_to_variant(self):
|
||||
variant = make_item_variant()
|
||||
self.assertNotEqual(variant.get("quality_parameters"), [])
|
||||
@@ -1144,7 +1144,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-06-13 14:29:12.567700",
|
||||
"modified": "2017-06-22 14:29:12.700000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Lead",
|
||||
|
||||
@@ -316,6 +316,8 @@ def setup_account():
|
||||
doc.parent_account = frappe.db.get_value('Account', {'account_name': doc.parent_account})
|
||||
doc.insert()
|
||||
|
||||
frappe.flags.in_import = False
|
||||
|
||||
def setup_account_to_expense_type():
|
||||
company_abbr = frappe.db.get_value("Company", erpnext.get_default_company(), "abbr")
|
||||
expense_types = [{'name': _('Calls'), "account": "Sales Expenses - "+ company_abbr},
|
||||
@@ -380,4 +382,6 @@ def import_json(doctype, submit=False, values=None):
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
frappe.flags.in_import = False
|
||||
|
||||
|
||||
|
||||
BIN
erpnext/docs/assets/img/accounts/pos_deleted_item.gif
Normal file
|
After Width: | Height: | Size: 426 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
BIN
erpnext/docs/assets/img/buying/purchase-taxes.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
erpnext/docs/assets/img/crm/sales-analytics-customer.gif
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
erpnext/docs/assets/img/crm/sales-partner-listing.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-1.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-2.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-3.gif
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-4.gif
Normal file
|
After Width: | Height: | Size: 568 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-5.gif
Normal file
|
After Width: | Height: | Size: 429 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-6.gif
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
erpnext/docs/assets/img/customize/kanban-board-7.gif
Normal file
|
After Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 261 KiB |
BIN
erpnext/docs/assets/img/manufacturing/subcontract.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
erpnext/docs/assets/img/manufacturing/subcontract2.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
erpnext/docs/assets/img/manufacturing/subcontract3.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
erpnext/docs/assets/img/manufacturing/subcontract4.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
erpnext/docs/assets/img/manufacturing/subcontract5.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
0
erpnext/docs/assets/img/regional/__init__.py
Normal file
0
erpnext/docs/assets/img/regional/india/__init__.py
Normal file
|
After Width: | Height: | Size: 215 KiB |
BIN
erpnext/docs/assets/img/regional/india/gst-in-coa.png
Normal file
|
After Width: | Height: | Size: 279 KiB |
BIN
erpnext/docs/assets/img/regional/india/gst-invoice.gif
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
erpnext/docs/assets/img/regional/india/gst-itemised.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
erpnext/docs/assets/img/regional/india/gst-menu.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
erpnext/docs/assets/img/regional/india/gst-settings.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
erpnext/docs/assets/img/regional/india/gst-template-in-state.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
erpnext/docs/assets/img/regional/india/gstin-company.gif
Normal file
|
After Width: | Height: | Size: 538 KiB |
BIN
erpnext/docs/assets/img/regional/india/gstin-customer.gif
Normal file
|
After Width: | Height: | Size: 789 KiB |
BIN
erpnext/docs/assets/img/regional/india/gstin-portal-update.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
erpnext/docs/assets/img/regional/india/gstin-reminder-email.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
erpnext/docs/assets/img/regional/india/hsn-item.gif
Normal file
|
After Width: | Height: | Size: 337 KiB |
|
After Width: | Height: | Size: 185 KiB |
BIN
erpnext/docs/assets/img/selling/Item-UOM.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
erpnext/docs/assets/img/selling/Sale-Order-UOM.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
erpnext/docs/assets/img/selling/portal-new-ticket.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
erpnext/docs/assets/img/selling/portal-ticket-1.gif
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
erpnext/docs/assets/img/selling/portal-ticket-list-empty.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
erpnext/docs/assets/img/selling/portal-ticket-reply.gif
Normal file
|
After Width: | Height: | Size: 565 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 58 KiB |
BIN
erpnext/docs/assets/img/selling/target-distribution.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
erpnext/docs/assets/img/setup/data-import/data-import-4.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
erpnext/docs/assets/img/setup/data-import/data-import-excel.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
BIN
erpnext/docs/assets/img/setup/sms-settings1.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
erpnext/docs/assets/img/setup/stock-reco-data.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
erpnext/docs/assets/img/setup/stock-reco-ledger.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
erpnext/docs/assets/img/setup/stock-reco-upload.gif
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 199 KiB |
|
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 173 KiB |