Merge pull request #32499 from rohitwaghchaure/fixed-TooManyWritesError-for-reposting
fix: TooManyWritesError during reposting of stock
diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
index 1a572d9..78c3526 100644
--- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
@@ -99,7 +99,7 @@
.where(loan_disbursement.clearance_date.isnull())
.where(loan_disbursement.disbursement_account.isin([self.bank_account, self.account]))
.orderby(loan_disbursement.disbursement_date)
- .orderby(loan_disbursement.name, frappe.qb.desc)
+ .orderby(loan_disbursement.name, order=frappe.qb.desc)
).run(as_dict=1)
loan_repayment = frappe.qb.DocType("Loan Repayment")
@@ -126,7 +126,9 @@
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
query = query.where((loan_repayment.repay_from_salary == 0))
- query = query.orderby(loan_repayment.posting_date).orderby(loan_repayment.name, frappe.qb.desc)
+ query = query.orderby(loan_repayment.posting_date).orderby(
+ loan_repayment.name, order=frappe.qb.desc
+ )
loan_repayments = query.run(as_dict=True)
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index 2ee356a..2f3516e 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -186,8 +186,10 @@
{
"fetch_from": "bank_account.bank",
"fieldname": "bank",
- "fieldtype": "Read Only",
- "label": "Bank"
+ "fieldtype": "Link",
+ "label": "Bank",
+ "options": "Bank",
+ "read_only": 1
},
{
"fetch_from": "bank_account.bank_account_no",
@@ -366,10 +368,11 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2020-09-18 12:24:14.178853",
+ "modified": "2022-09-30 16:19:43.680025",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Request",
+ "naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
@@ -401,5 +404,6 @@
}
],
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 782e08e..ce44ae3 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -8,7 +8,7 @@
from frappe.model.dynamic_links import get_dynamic_link_map
from frappe.model.naming import make_autoname
from frappe.tests.utils import change_settings
-from frappe.utils import add_days, flt, getdate, nowdate
+from frappe.utils import add_days, flt, getdate, nowdate, today
import erpnext
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
@@ -3196,6 +3196,37 @@
"Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice", unlink_enabled
)
+ def test_batch_expiry_for_sales_invoice_return(self):
+ from erpnext.controllers.sales_and_purchase_return import make_return_doc
+ from erpnext.stock.doctype.item.test_item import make_item
+
+ item = make_item(
+ "_Test Batch Item For Return Check",
+ {
+ "is_purchase_item": 1,
+ "is_stock_item": 1,
+ "has_batch_no": 1,
+ "create_new_batch": 1,
+ "batch_number_series": "TBIRC.#####",
+ },
+ )
+
+ pr = make_purchase_receipt(qty=1, item_code=item.name)
+
+ batch_no = pr.items[0].batch_no
+ si = create_sales_invoice(qty=1, item_code=item.name, update_stock=1, batch_no=batch_no)
+
+ si.load_from_db()
+ batch_no = si.items[0].batch_no
+ self.assertTrue(batch_no)
+
+ frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+ return_si = make_return_doc(si.doctype, si.name)
+ return_si.save().submit()
+
+ self.assertTrue(return_si.docstatus == 1)
+
def get_sales_invoice_for_e_invoice():
si = make_sales_invoice_for_ewaybill()
@@ -3289,6 +3320,7 @@
"serial_no": args.serial_no,
"conversion_factor": 1,
"incoming_rate": args.incoming_rate or 0,
+ "batch_no": args.batch_no or None,
},
)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index c5eb7d8..9ede678 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -86,7 +86,7 @@
)
)
- query = query.orderby(FY.year_start_date, Order.desc)
+ query = query.orderby(FY.year_start_date, order=Order.desc)
fiscal_years = query.run(as_dict=True)
frappe.cache().hset("fiscal_years", company, fiscal_years)
diff --git a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py
index 062d24b..fd2a2a3 100644
--- a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py
+++ b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py
@@ -3,6 +3,29 @@
from frappe.utils import create_batch
+def remove_duplicate_entries(pl_entries):
+ unique_vouchers = set()
+ for x in pl_entries:
+ unique_vouchers.add(
+ (x.company, x.account, x.party_type, x.party, x.voucher_type, x.voucher_no, x.gle_remarks)
+ )
+
+ entries = []
+ for x in unique_vouchers:
+ entries.append(
+ frappe._dict(
+ company=x[0],
+ account=x[1],
+ party_type=x[2],
+ party=x[3],
+ voucher_type=x[4],
+ voucher_no=x[5],
+ gle_remarks=x[6],
+ )
+ )
+ return entries
+
+
def execute():
if frappe.reload_doc("accounts", "doctype", "payment_ledger_entry"):
@@ -34,6 +57,8 @@
.run(as_dict=True)
)
+ pl_entries = remove_duplicate_entries(pl_entries)
+
if pl_entries:
# split into multiple batches, update and commit for each batch
batch_size = 1000
diff --git a/erpnext/public/scss/order-page.scss b/erpnext/public/scss/order-page.scss
new file mode 100644
index 0000000..6f5fe5d
--- /dev/null
+++ b/erpnext/public/scss/order-page.scss
@@ -0,0 +1,115 @@
+#page-order {
+ .main-column {
+ .page-content-wrapper {
+
+ .breadcrumb-container {
+ @media screen and (min-width: 567px) {
+ padding-left: var(--padding-sm);
+ }
+ }
+
+ .container.my-4 {
+ background-color: var(--fg-color);
+
+ @media screen and (min-width: 567px) {
+ padding: 1.25rem 1.5rem;
+ border-radius: var(--border-radius-md);
+ box-shadow: var(--card-shadow);
+ }
+ }
+ }
+ }
+}
+
+.indicator-container {
+ @media screen and (max-width: 567px) {
+ padding-bottom: 0.8rem;
+ }
+}
+
+.order-items {
+ padding: 1.5rem 0;
+ border-bottom: 1px solid var(--border-color);
+ color: var(--gray-700);
+
+ @media screen and (max-width: 567px) {
+ align-items: flex-start !important;
+ }
+ .col-2 {
+ @media screen and (max-width: 567px) {
+ flex: auto;
+ max-width: 28%;
+ }
+ }
+
+ .order-item-name {
+ font-size: var(--text-base);
+ font-weight: 500;
+ }
+
+ .btn:focus,
+ .btn:hover {
+ background-color: var(--control-bg);
+ }
+
+
+ .col-6 {
+ @media screen and (max-width: 567px) {
+ max-width: 100%;
+ }
+
+ &.order-item-name {
+ font-size: var(--text-base);
+ }
+ }
+}
+
+.item-grand-total {
+ font-size: var(--text-base);
+}
+
+.list-item-name,
+.item-total,
+.order-container,
+.order-qty {
+ font-size: var(--text-md);
+}
+
+.d-s-n {
+ @media screen and (max-width: 567px) {
+ display: none;
+ }
+}
+
+.d-l-n {
+ @media screen and (min-width: 567px) {
+ display: none;
+ }
+}
+
+.border-btm {
+ border-bottom: 1px solid var(--border-color);
+}
+
+.order-taxes {
+ display: flex;
+
+ @media screen and (min-width: 567px) {
+ justify-content: flex-end;
+ }
+
+ .col-4 {
+ padding-right: 0;
+
+ .col-8 {
+ padding-left: 0;
+ padding-right: 0;
+ }
+
+ @media screen and (max-width: 567px) {
+ padding-left: 0;
+ flex: auto;
+ max-width: 100%;
+ }
+ }
+}
\ No newline at end of file
diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss
index 9ea8416..b5e97f1 100644
--- a/erpnext/public/scss/website.scss
+++ b/erpnext/public/scss/website.scss
@@ -1,3 +1,4 @@
+@import './order-page';
.filter-options {
max-height: 300px;
@@ -32,19 +33,29 @@
height: 24px;
}
-.website-list .result {
- margin-top: 2rem;
-}
+.website-list {
+ background-color: var(--fg-color);
+ padding: 0 var(--padding-lg);
+ border-radius: var(--border-radius-md);
-.result {
- border-bottom: 1px solid var(--border-color);
+ @media screen and (max-width: 567px) {
+ margin-left: -2rem;
+ }
+
+ &.result {
+ border-bottom: 1px solid var(--border-color);
+ }
}
.transaction-list-item {
padding: 1rem 0;
- border-top: 1px solid var(--border-color);
+ border-bottom: 1px solid var(--border-color);
position: relative;
+ &:only-child, &:last-child {
+ border: 0;
+ }
+
a.transaction-item-link {
position: absolute;
top: 0;
@@ -68,3 +79,13 @@
line-height: 1.3;
}
}
+
+.list-item-name, .item-total {
+ font-size: var(--font-size-sm);
+}
+
+.items-preview {
+ @media screen and (max-width: 567px) {
+ margin-top: 1rem;
+ }
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 6bcab73..1b9f168 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -6,7 +6,7 @@
import frappe
from frappe.tests.utils import FrappeTestCase
-from frappe.utils import cstr, flt, nowdate, nowtime
+from frappe.utils import add_days, cstr, flt, nowdate, nowtime, today
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.accounts.utils import get_balance_on
@@ -1091,6 +1091,36 @@
frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype})
)
+ def test_batch_expiry_for_delivery_note(self):
+ from erpnext.controllers.sales_and_purchase_return import make_return_doc
+ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+
+ item = make_item(
+ "_Test Batch Item For Return Check",
+ {
+ "is_purchase_item": 1,
+ "is_stock_item": 1,
+ "has_batch_no": 1,
+ "create_new_batch": 1,
+ "batch_number_series": "TBIRC.#####",
+ },
+ )
+
+ pi = make_purchase_receipt(qty=1, item_code=item.name)
+
+ dn = create_delivery_note(qty=1, item_code=item.name, batch_no=pi.items[0].batch_no)
+
+ dn.load_from_db()
+ batch_no = dn.items[0].batch_no
+ self.assertTrue(batch_no)
+
+ frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+ return_dn = make_return_doc(dn.doctype, dn.name)
+ return_dn.save().submit()
+
+ self.assertTrue(return_dn.docstatus == 1)
+
def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note")
@@ -1117,6 +1147,7 @@
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no,
+ "batch_no": args.batch_no or None,
"target_warehouse": args.target_warehouse,
},
)
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index adddb41..9c1c7e5 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -183,7 +183,7 @@
frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx))
item_code = item.item_code
reference = item.sales_order_item or item.material_request_item
- key = (item_code, item.uom, item.warehouse, reference)
+ key = (item_code, item.uom, item.warehouse, item.batch_no, reference)
item.idx = None
item.name = None
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index f7f8cbe..c64370d 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -153,7 +153,9 @@
def validate_batch(self):
if self.batch_no and self.voucher_type != "Stock Entry":
- if self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0:
+ if (self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0) or (
+ self.voucher_type in ["Delivery Note", "Sales Invoice"] and self.actual_qty > 0
+ ):
return
expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date")
diff --git a/erpnext/templates/includes/footer/footer_extension.html b/erpnext/templates/includes/footer/footer_extension.html
index c7f0d06..0072dc2 100644
--- a/erpnext/templates/includes/footer/footer_extension.html
+++ b/erpnext/templates/includes/footer/footer_extension.html
@@ -6,7 +6,7 @@
aria-label="{{ _('Your email address...') }}"
aria-describedby="footer-subscribe-button">
<div class="input-group-append">
- <button class="btn btn-sm btn-default"
+ <button class="btn btn-sm btn-secondary pl-3 pr-3 ml-2"
type="button" id="footer-subscribe-button">{{ _("Get Updates") }}</button>
</div>
</div>
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index f56dc3a..dc9ee23 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -1,5 +1,5 @@
{% macro product_image_square(website_image, css_class="") %}
-<div class="product-image product-image-square
+<div class="product-image product-image-square h-100 rounded
{% if not website_image -%} missing-image {%- endif %} {{ css_class }}"
{% if website_image -%}
style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');"
diff --git a/erpnext/templates/includes/order/order_macros.html b/erpnext/templates/includes/order/order_macros.html
index 3f2c1f2..d95b289 100644
--- a/erpnext/templates/includes/order/order_macros.html
+++ b/erpnext/templates/includes/order/order_macros.html
@@ -3,7 +3,7 @@
{% macro item_name_and_description(d) %}
<div class="row item_name_and_description">
<div class="col-xs-4 col-sm-2 order-image-col">
- <div class="order-image">
+ <div class="order-image h-100">
{% if d.thumbnail or d.image %}
{{ product_image(d.thumbnail or d.image, no_border=True) }}
{% else %}
@@ -18,6 +18,9 @@
<div class="text-muted small item-description">
{{ html2text(d.description) | truncate(140) }}
</div>
+ <span class="text-muted mt-2 d-l-n order-qty">
+ {{ _("Qty ") }}({{ d.get_formatted("qty") }})
+ </span>
</div>
</div>
{% endmacro %}
diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html
index b821e62..0060ab3 100644
--- a/erpnext/templates/includes/order/order_taxes.html
+++ b/erpnext/templates/includes/order/order_taxes.html
@@ -1,84 +1,111 @@
{% if doc.taxes %}
-<tr>
- <td class="text-left" colspan="1">
- {{ _("Net Total") }}
- </td>
- <td class="text-right totals" colspan="3">
- {{ doc.get_formatted("net_total") }}
- </td>
-</tr>
+ <div class="w-100 order-taxes mt-5">
+ <div class="col-4 d-flex border-btm pb-5">
+ <div class="item-grand-total col-8">
+ {{ _("Net Total") }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ {{ doc.get_formatted("net_total") }}
+ </div>
+ </div>
+ </div>
{% endif %}
{% for d in doc.taxes %}
{% if d.base_tax_amount %}
- <tr>
- <td class="text-left" colspan="1">
- {{ d.description }}
- </td>
- <td class="text-right totals" colspan="3">
- {{ d.get_formatted("base_tax_amount") }}
- </td>
- </tr>
+ <div class="order-taxes w-100 mt-5">
+ <div class="col-4 d-flex border-btm pb-5">
+ <div class="item-grand-total col-8">
+ {{ d.description }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ {{ doc.get_formatted("net_total") }}
+ </div>
+ </div>
+ </div>
{% endif %}
{% endfor %}
{% if doc.doctype == 'Quotation' %}
{% if doc.coupon_code %}
- <tr>
- <td class="text-left total-discount" colspan="1">
- {{ _("Savings") }}
- </td>
- <td class="text-right tot_quotation_discount total-discount totals" colspan="3">
- {% set tot_quotation_discount = [] %}
- {%- for item in doc.items -%}
- {% if tot_quotation_discount.append((((item.price_list_rate * item.qty)
- * item.discount_percentage) / 100)) %}
- {% endif %}
- {% endfor %}
- {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }}
- </td>
- </tr>
+ <div class="w-100 mt-5 order-taxes font-weight-bold">
+ <div class="col-4 d-flex border-btm pb-5">
+ <div class="item-grand-total col-8">
+ {{ _("Savings") }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ {% set tot_quotation_discount = [] %}
+ {%- for item in doc.items -%}
+ {% if tot_quotation_discount.append((((item.price_list_rate * item.qty)
+ * item.discount_percentage) / 100)) %}
+ {% endif %}
+ {% endfor %}
+ {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }} </div>
+ </div>
+ </div>
{% endif %}
{% endif %}
{% if doc.doctype == 'Sales Order' %}
{% if doc.coupon_code %}
- <tr>
- <td class="text-left total-discount" colspan="2" style="padding-right: 2rem;">
- {{ _("Applied Coupon Code") }}
- </td>
- <td class="text-right total-discount">
- <span>
- {%- for row in frappe.get_all(doctype="Coupon Code",
- fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%}
- <span>{{ row.coupon_code }}</span>
- {% endfor %}
- </span>
- </td>
- </tr>
- <tr>
- <td class="text-left total-discount" colspan="2">
- {{ _("Savings") }}
- </td>
- <td class="text-right total-discount">
- <span>
- {% set tot_SO_discount = [] %}
- {%- for item in doc.items -%}
- {% if tot_SO_discount.append((((item.price_list_rate * item.qty)
- * item.discount_percentage) / 100)) %}{% endif %}
- {% endfor %}
- {{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }}
- </span>
- </td>
- </tr>
+ <div class="w-100 order-taxes mt-5">
+ <div class="col-4 d-flex border-btm pb-5">
+ <div class="item-grand-total col-8">
+ {{ _("Total Amount") }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ <span>
+ {% set total_amount = [] %}
+ {%- for item in doc.items -%}
+ {% if total_amount.append((item.price_list_rate * item.qty)) %}{% endif %}
+ {% endfor %}
+ {{ frappe.utils.fmt_money((total_amount | sum),currency=doc.currency) }}
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="order-taxes w-100 mt-5">
+ <div class="col-4 d-flex">
+ <div class="item-grand-total col-8">
+ {{ _("Applied Coupon Code") }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ <span>
+ {%- for row in frappe.get_all(doctype="Coupon Code",
+ fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%}
+ <span>{{ row.coupon_code }}</span>
+ {% endfor %}
+ </span>
+ </div>
+ </div>
+ </div>
+ <div class="order-taxes mt-5">
+ <div class="col-4 d-flex border-btm pb-5">
+ <div class="item-grand-total col-8">
+ {{ _("Savings") }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ <span>
+ {% set tot_SO_discount = [] %}
+ {%- for item in doc.items -%}
+ {% if tot_SO_discount.append((((item.price_list_rate * item.qty)
+ * item.discount_percentage) / 100)) %}{% endif %}
+ {% endfor %}
+ {{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }}
+ </span>
+ </div>
+ </div>
+ </div>
{% endif %}
{% endif %}
-<tr>
- <th class="text-left item-grand-total" colspan="1">
- {{ _("Grand Total") }}
- </th>
- <th class="text-right item-grand-total totals" colspan="3">
- {{ doc.get_formatted("grand_total") }}
- </th>
-</tr>
+<div class="w-100 mt-5 order-taxes font-weight-bold">
+ <div class="col-4 d-flex">
+ <div class="item-grand-total col-8">
+ {{ _("Grand Total") }}
+ </div>
+ <div class="item-grand-total col-4 text-right pr-0">
+ {{ doc.get_formatted("grand_total") }}
+ </div>
+ </div>
+</div>
diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html
index 3cfb8d8..72d498c 100644
--- a/erpnext/templates/includes/transaction_row.html
+++ b/erpnext/templates/includes/transaction_row.html
@@ -1,20 +1,22 @@
<div class="web-list-item transaction-list-item">
- <div class="row">
+ <div class="row align-items-center">
<div class="col-sm-4">
- <span class="indicator small {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "gray") }}">
- {{ doc.name }}</span>
+ <span class="list-item-name font-weight-bold">{{ doc.name }}</span>
<div class="small text-muted transaction-time"
title="{{ frappe.utils.format_datetime(doc.modified, "medium") }}">
{{ frappe.utils.global_date_format(doc.modified) }}
</div>
</div>
- <div class="col-sm-5">
+ <div class="col-sm-3">
+ <span class="indicator-pill {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "gray") }} list-item-status">{{doc.status}}</span>
+ </div>
+ <div class="col-sm-2">
<div class="small text-muted items-preview ellipsis ellipsis-width">
{{ doc.items_preview }}
</div>
</div>
{% if doc.get('grand_total') %}
- <div class="col-sm-3 text-right bold">
+ <div class="col-sm-3 text-right font-weight-bold item-total">
{{ doc.get_formatted("grand_total") }}
</div>
{% endif %}
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
index ec1d497..6b354b2 100644
--- a/erpnext/templates/pages/order.html
+++ b/erpnext/templates/pages/order.html
@@ -5,149 +5,159 @@
{% include "templates/includes/breadcrumbs.html" %}
{% endblock %}
-{% block title %}{{ doc.name }}{% endblock %}
+{% block title %}
+ {{ doc.name }}
+{% endblock %}
{% block header %}
- <h2 class="m-0">{{ doc.name }}</h2>
+ <h3 class="m-0">{{ doc.name }}</h3>
{% endblock %}
{% block header_actions %}
- <div class="dropdown">
- <button class="btn btn-outline-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- <span class="font-md">{{ _('Actions') }}</span>
- <b class="caret"></b>
- </button>
- <ul class="dropdown-menu dropdown-menu-right" role="menu">
- {% if doc.doctype == 'Purchase Order' and show_make_pi_button %}
- <a class="dropdown-item" href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}" data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}</a>
- {% endif %}
- <a class="dropdown-item" href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}'
- target="_blank" rel="noopener noreferrer">
- {{ _("Print") }}
- </a>
- </ul>
+ <div class="row">
+ <div class="dropdown">
+ <button class="btn btn-sm btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+ <span class="font-md">{{ _('Actions') }}</span>
+ <b class="caret"></b>
+ </button>
+ <ul class="dropdown-menu dropdown-menu-right" role="menu">
+ {% if doc.doctype == 'Purchase Order' and show_make_pi_button %}
+ <a class="dropdown-item"
+ href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}"
+ data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}
+ </a>
+ {% endif %}
+ <a class="dropdown-item"
+ href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}' target="_blank"
+ rel="noopener noreferrer">
+ {{ _("Print") }}
+ </a>
+ </ul>
+ </div>
+ <div class="form-column col-sm-6">
+ <div class="page-header-actions-block" data-html-block="header-actions">
+ <p>
+ <a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&order_type=Shopping Cart"
+ class="btn btn-primary btn-sm" id="pay-for-order">
+ {{ _("Pay") }} {{doc.get_formatted("grand_total") }}
+ </a>
+ </p>
+ </div>
+ </div>
</div>
{% endblock %}
{% block page_content %}
- <div class="row transaction-subheading">
- <div class="col-6">
- <span class="font-md indicator-pill {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "darkgrey") }}">
- {% if doc.doctype == "Quotation" and not doc.docstatus %}
- {{ _("Pending") }}
- {% else %}
- {{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
+ <div>
+ <div class="row transaction-subheading mt-1">
+ <div class="col-6 text-muted small mt-1">
+ {{ frappe.utils.format_date(doc.transaction_date, 'medium') }}
+ {% if doc.valid_till %}
+ <p>
+ {{ _("Valid Till") }}: {{ frappe.utils.format_date(doc.valid_till, 'medium') }}
+ </p>
{% endif %}
- </span>
+ </div>
</div>
- <div class="col-6 text-muted text-right small pt-3">
- {{ frappe.utils.format_date(doc.transaction_date, 'medium') }}
- {% if doc.valid_till %}
- <p>
- {{ _("Valid Till") }}: {{ frappe.utils.format_date(doc.valid_till, 'medium') }}
- </p>
- {% endif %}
- </div>
- </div>
-
- <p class="small my-3">
- {%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase Order'] else doc.customer_name %}
- <b>{{ party_name }}</b>
-
- {% if doc.contact_display and doc.contact_display != party_name %}
- <br>
- {{ doc.contact_display }}
- {% endif %}
- </p>
-
- {% if doc._header %}
- {{ doc._header }}
- {% endif %}
-
- <div class="order-container">
- <!-- items -->
- <table class="order-item-table w-100 table">
- <thead class="order-items order-item-header">
- <th width="60%">
- {{ _("Item") }}
- </th>
- <th width="20%" class="text-right">
- {{ _("Quantity") }}
- </th>
- <th width="20%" class="text-right">
- {{ _("Amount") }}
- </th>
- </thead>
- <tbody>
- {% for d in doc.items %}
- <tr class="order-items">
- <td>
- {{ item_name_and_description(d) }}
- </td>
- <td class="text-right">
- {{ d.qty }}
- {% if d.delivered_qty is defined and d.delivered_qty != None %}
- <p class="text-muted small">{{ _("Delivered") }} {{ d.delivered_qty }}</p>
+ <div class="row indicator-container mt-2">
+ <div class="col-10">
+ <span class="indicator-pill {{ doc.indicator_color or (" blue" if doc.docstatus==1 else "darkgrey" ) }}">
+ {% if doc.doctype == "Quotation" and not doc.docstatus %}
+ {{ _("Pending") }}
+ {% else %}
+ {{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
{% endif %}
- </td>
- <td class="text-right">
- {{ d.get_formatted("amount") }}
- <p class="text-muted small">{{ _("Rate:") }} {{ d.get_formatted("rate") }}</p>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- <!-- taxes -->
- <div class="order-taxes d-flex justify-content-end">
- <table>
+ </span>
+ </div>
+ <div class="text-right col-2">
+ {%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase
+ Order'] else doc.customer_name %}
+ <b>{{ party_name }}</b>
+
+ {% if doc.contact_display and doc.contact_display != party_name %}
+ <br>
+ {{ doc.contact_display }}
+ {% endif %}
+ </div>
+ </div>
+
+ {% if doc._header %}
+ {{ doc._header }}
+ {% endif %}
+
+ <div class="order-container mt-4">
+ <!-- items -->
+ <div class="w-100">
+ <div class="order-items order-item-header mb-1 row text-muted">
+ <span class="col-5">
+ {{ _("Item") }}
+ </span>
+ <span class="d-s-n col-3">
+ {{ _("Quantity") }}
+ </span>
+ <span class="col-2 pl-10">
+ {{ _("Rate") }}
+ </span>
+ <span class="col-2 text-right">
+ {{ _("Amount") }}
+ </span>
+ </div>
+ {% for d in doc.items %}
+ <div class="order-items row align-items-center">
+ <span class="order-item-name col-5 pr-0">
+ {{ item_name_and_description(d) }}
+ </span>
+
+ <span class="d-s-n col-3 pl-10">
+ {{ d.get_formatted("qty") }}
+ </span>
+ <span class="order-rate pl-4 col-2">
+ {{ d.get_formatted("rate") }}
+ </span>
+ <span class="col-2 text-right">
+ {{ d.get_formatted("amount") }}
+ </span>
+ </div>
+ {% endfor %}
+ </div>
+
+ <!-- taxes -->
+ <div class="">
{% include "erpnext/templates/includes/order/order_taxes.html" %}
- </table>
+ </div>
</div>
</div>
{% if enabled_checkout and ((doc.doctype=="Sales Order" and doc.per_billed <= 0)
- or (doc.doctype=="Sales Invoice" and doc.outstanding_amount > 0)) %}
+ or (doc.doctype=="Sales Invoice" and doc.outstanding_amount> 0)) %}
<div class="panel panel-default">
- <div class="panel-heading">
- <div class="row">
- <div class="form-column col-sm-6 address-title">
- <strong>Payment</strong>
- </div>
- </div>
- </div>
<div class="panel-collapse">
<div class="panel-body text-muted small">
<div class="row">
<div class="form-column col-sm-6">
{% if available_loyalty_points %}
+ <div class="panel-heading">
+ <div class="row">
+ <div class="form-column col-sm-6 address-title">
+ <strong>Loyalty Points</strong>
+ </div>
+ </div>
+ </div>
+
<div class="form-group">
<div class="h6">Enter Loyalty Points</div>
<div class="control-input-wrapper">
<div class="control-input">
- <input class="form-control" type="number" min="0" max="{{ available_loyalty_points }}" id="loyalty-point-to-redeem">
+ <input class="form-control" type="number" min="0"
+ max="{{ available_loyalty_points }}" id="loyalty-point-to-redeem">
</div>
- <p class="help-box small text-muted d-none d-sm-block"> Available Points: {{ available_loyalty_points }} </p>
+ <p class="help-box small text-muted d-none d-sm-block"> Available Points: {{
+ available_loyalty_points }} </p>
</div>
</div>
{% endif %}
</div>
-
- <div class="form-column col-sm-6">
- <div id="loyalty-points-status" style="text-align: right"></div>
- <div class="page-header-actions-block" data-html-block="header-actions">
- <p class="mt-2" style="float: right;">
- <a href="/api/method/erpnext.accounts.doctype.payment_request.payment_request.make_payment_request?dn={{ doc.name }}&dt={{ doc.doctype }}&submit_doc=1&order_type=Shopping Cart"
- class="btn btn-primary btn-sm"
- id="pay-for-order">
- {{ _("Pay") }} {{ doc.get_formatted("grand_total") }}
- </a>
- </p>
- </div>
- </div>
-
</div>
-
</div>
</div>
</div>
@@ -172,17 +182,17 @@
</div>
</div>
{% endif %}
- </div>
{% if doc.terms %}
<div class="terms-and-condition text-muted small">
- <hr><p>{{ doc.terms }}</p>
+ <hr>
+ <p>{{ doc.terms }}</p>
</div>
{% endif %}
{% endblock %}
{% block script %}
- <script> {% include "templates/pages/order.js" %} </script>
+ <script> {% include "templates/pages/order.js" %}</script>
<script>
window.doc_info = {
customer: '{{doc.customer}}',
@@ -192,4 +202,4 @@
currency: '{{ doc.currency }}'
}
</script>
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py
index bfcba07..eed7c12 100644
--- a/erpnext/utilities/bulk_transaction.py
+++ b/erpnext/utilities/bulk_transaction.py
@@ -9,7 +9,6 @@
def transaction_processing(data, from_doctype, to_doctype):
if isinstance(data, str):
deserialized_data = json.loads(data)
-
else:
deserialized_data = data
@@ -30,30 +29,29 @@
def job(deserialized_data, from_doctype, to_doctype):
- failed_history = []
- i = 0
+ fail_count = 0
for d in deserialized_data:
- failed = []
-
try:
- i += 1
doc_name = d.get("name")
frappe.db.savepoint("before_creation_state")
task(doc_name, from_doctype, to_doctype)
-
except Exception as e:
frappe.db.rollback(save_point="before_creation_state")
- failed_history.append(e)
- failed.append(e)
+ fail_count += 1
update_logger(
- doc_name, e, from_doctype, to_doctype, status="Failed", log_date=str(date.today())
+ doc_name,
+ str(frappe.get_traceback()),
+ from_doctype,
+ to_doctype,
+ status="Failed",
+ log_date=str(date.today()),
)
- if not failed:
+ else:
update_logger(
doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today())
)
- show_job_status(failed_history, deserialized_data, to_doctype)
+ show_job_status(fail_count, len(deserialized_data), to_doctype)
def task(doc_name, from_doctype, to_doctype):
@@ -94,7 +92,7 @@
"Purchase Invoice": purchase_order.make_purchase_invoice,
"Purchase Receipt": purchase_order.make_purchase_receipt,
},
- "Purhcase Invoice": {
+ "Purchase Invoice": {
"Purchase Receipt": purchase_invoice.make_purchase_receipt,
"Payment": payment_entry.get_payment_entry,
},
@@ -150,15 +148,14 @@
log_doc.save()
-def show_job_status(failed_history, deserialized_data, to_doctype):
- if not failed_history:
+def show_job_status(fail_count, deserialized_data_count, to_doctype):
+ if not fail_count:
frappe.msgprint(
_("Creation of {0} successful").format(to_doctype),
title="Successful",
indicator="green",
)
-
- if len(failed_history) != 0 and len(failed_history) < len(deserialized_data):
+ elif fail_count != 0 and fail_count < deserialized_data_count:
frappe.msgprint(
_(
"""Creation of {0} partially successful.
@@ -167,8 +164,7 @@
title="Partially successful",
indicator="orange",
)
-
- if len(failed_history) == len(deserialized_data):
+ else:
frappe.msgprint(
_(
"""Creation of {0} failed.
@@ -180,9 +176,7 @@
def record_exists(log_doc, doc_name, status):
-
record = mark_retrired_transaction(log_doc, doc_name)
-
if record and status == "Failed":
return False
elif record and status == "Success":
diff --git a/erpnext/www/book_appointment/index.css b/erpnext/www/book_appointment/index.css
index 2776108..3b1b97c 100644
--- a/erpnext/www/book_appointment/index.css
+++ b/erpnext/www/book_appointment/index.css
@@ -45,7 +45,7 @@
.time-slot.selected {
color: white;
- background: #5e64ff;
+ background: var(--primary-color);
}
.time-slot.selected .text-muted {