[IMP] donation_details_lines: add donation amount field; update donation catalog controls for better quantity handling
This commit is contained in:
parent
a9c94d5f0c
commit
aebf600ed6
|
|
@ -388,6 +388,7 @@ class DonationsDetailsLines(models.Model):
|
|||
"donation_types": 'donation',
|
||||
"name": product.name,
|
||||
"donation_qty": _qty,
|
||||
"donation_amount": product.lst_price
|
||||
})
|
||||
else:
|
||||
if existing:
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@ class TakafulSponsorship(models.Model):
|
|||
"donation_types": 'donation',
|
||||
"name": product.name,
|
||||
"donation_qty": _qty,
|
||||
"donation_amount": product.lst_price
|
||||
})
|
||||
else:
|
||||
# remove if qty <= 0
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@
|
|||
|
||||
// Attach event handlers immediately using event delegation
|
||||
// Odoo converts 'name' attribute to 'data-name' in rendered HTML
|
||||
$(document).on('click', 'button[data-name="add_quantity_button_request"]', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleQuantityChange($(this), 'first_add');
|
||||
return false; // ensure Odoo's default kanban action handler does not run
|
||||
});
|
||||
|
||||
$(document).on('click', 'button[data-name="add_quantity_button_so"]', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -24,6 +31,9 @@ window.__dc_add = function(btn) {
|
|||
window.__dc_remove = function(btn) {
|
||||
return __dc_handle(btn, 'remove');
|
||||
};
|
||||
window.__dc_first_add = function(btn) {
|
||||
return __dc_handle(btn, 'first_add');
|
||||
};
|
||||
|
||||
function __dc_handle(btn, operation) {
|
||||
try {
|
||||
|
|
@ -36,6 +46,7 @@ function __dc_handle(btn, operation) {
|
|||
}
|
||||
|
||||
async function handleQuantityChange($button, operation) {
|
||||
|
||||
// Get the kanban record (product card) container
|
||||
const $kanbanRecord = $button.closest('.o_kanban_record');
|
||||
if (!$kanbanRecord.length) {
|
||||
|
|
@ -43,24 +54,26 @@ async function handleQuantityChange($button, operation) {
|
|||
}
|
||||
|
||||
// Get quantity display element from the button's parent container using stable custom classes
|
||||
const $container = $button.closest('.dc-qty-controls');
|
||||
const $quantityDisplay = $container.find('.dc-qty-badge');
|
||||
|
||||
if (!$quantityDisplay.length) {
|
||||
return;
|
||||
let $container = $button.closest('.dc-qty-controls');
|
||||
if (operation === 'first_add'){
|
||||
$container = $kanbanRecord.find('.dc-qty-controls')
|
||||
}
|
||||
let $quantityDisplay = $container.find('.dc-qty-badge');
|
||||
// if (!$quantityDisplay.length) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Extract product ID from the image URL
|
||||
const $img = $kanbanRecord.find('.o_kanban_image img');
|
||||
if (!$img.length) {
|
||||
return;
|
||||
}
|
||||
// if (!$img.length) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const imgSrc = $img.attr('src');
|
||||
const match = imgSrc.match(/[&?]id=(\d+)/);
|
||||
if (!match || !match[1]) {
|
||||
return;
|
||||
}
|
||||
// if (!match || !match[1]) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const productId = parseInt(match[1]);
|
||||
let currentQuantity = parseFloat($quantityDisplay.text()) || 0;
|
||||
|
|
@ -68,10 +81,6 @@ async function handleQuantityChange($button, operation) {
|
|||
|
||||
// Prevent going below zero for remove operation
|
||||
if (operation === 'remove' && currentQuantity <= 0) {
|
||||
$quantityDisplay.addClass('bg-warning').removeClass('bg-secondary');
|
||||
setTimeout(() => {
|
||||
$quantityDisplay.removeClass('bg-warning').addClass('bg-secondary');
|
||||
}, 300);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -108,16 +117,22 @@ async function handleQuantityChange($button, operation) {
|
|||
|
||||
// Calculate new quantity
|
||||
let newQuantity = currentQuantity;
|
||||
if (operation === 'add') {
|
||||
newQuantity += 1;
|
||||
} else if (operation === 'remove') {
|
||||
newQuantity -= 1;
|
||||
if (operation === 'first_add'){
|
||||
$button.addClass('d-none');
|
||||
$kanbanRecord.find('.dc-qty-controls').removeClass("d-none");
|
||||
}
|
||||
|
||||
if (operation === 'add' || operation === 'first_add') {
|
||||
newQuantity = newQuantity + 1;
|
||||
}
|
||||
|
||||
if (operation === 'remove') {
|
||||
newQuantity = newQuantity - 1;
|
||||
}
|
||||
|
||||
// Update display optimistically
|
||||
$quantityDisplay.text(newQuantity.toFixed(2));
|
||||
|
||||
|
||||
try {
|
||||
// Call server to update quantity
|
||||
await $.ajax({
|
||||
|
|
@ -139,22 +154,13 @@ async function handleQuantityChange($button, operation) {
|
|||
throw info;
|
||||
});
|
||||
|
||||
// Visual feedback - flash color based on operation
|
||||
if (operation === 'add') {
|
||||
$quantityDisplay.addClass('bg-success').removeClass('bg-secondary');
|
||||
} else {
|
||||
$quantityDisplay.addClass('bg-info').removeClass('bg-secondary');
|
||||
}
|
||||
setTimeout(() => {
|
||||
$quantityDisplay.removeClass('bg-success bg-info').addClass('bg-secondary');
|
||||
}, 300);
|
||||
|
||||
} catch (error) {
|
||||
// Revert on error
|
||||
$quantityDisplay.text(currentQuantity.toFixed(2));
|
||||
$quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
|
||||
// $quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
|
||||
setTimeout(() => {
|
||||
$quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
|
||||
// $quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
|
||||
}, 1000);
|
||||
} finally {
|
||||
// Re-enable buttons
|
||||
|
|
|
|||
|
|
@ -4,34 +4,37 @@
|
|||
<field name="model">product.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban edit="0" create="0" class="o_kanban_mobile o_cart_kanban">
|
||||
<field name="id"/>
|
||||
<field name="name"/>
|
||||
<field name="_quantity"/>
|
||||
<field name="id" />
|
||||
<field name="name" />
|
||||
<field name="_quantity" />
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="o_product_quantity d-flex flex-column justify-content-between"
|
||||
style="min-height: 100px;width: 25%;">
|
||||
<div class="o_kanban_image">
|
||||
style="min-height: 100px;width: 25%;">
|
||||
<div class="o_kanban_image" style="display: flex;width: 100%;justify-content: space-between;align-items: center;">
|
||||
<img t-att-src="kanban_image('product.template', 'image_128', record.id.raw_value)"
|
||||
alt="Product" class="o_image_64_contain"/>
|
||||
alt="Product" class="o_image_64_contain" style="width: 100%;object-fit: cover;height: 100px;"/>
|
||||
</div>
|
||||
<h5 style="margin-top: 5px;text-align: center;">
|
||||
<span>Amount:</span>
|
||||
<field name="lst_price" widget="monetary" options="{'currency_field': 'currency_id'}" />
|
||||
</h5>
|
||||
<div class="oe_kanban_details p-2 d-flex">
|
||||
<div class="o_kanban_record_top flex-column w-100 "
|
||||
style="justify-content: space-between;">
|
||||
<div class="o_kanban_record_title">
|
||||
style="justify-content: space-between;">
|
||||
<div class="o_kanban_record_title w-100" style="text-align: center;">
|
||||
<strong>
|
||||
<field name="name"/>
|
||||
<field name="name" />
|
||||
</strong>
|
||||
</div>
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<ul>
|
||||
<!-- <ul>
|
||||
<li>
|
||||
<strong>
|
||||
Price:
|
||||
<field name="lst_price" widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
<strong> Amount: <field name="lst_price"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}" />
|
||||
</strong>
|
||||
</li>
|
||||
</li> -->
|
||||
|
||||
<!-- <field name="currency_id" invisible="1"/> -->
|
||||
<!-- <div> -->
|
||||
|
|
@ -40,77 +43,51 @@
|
|||
<!-- <field name="uom_id" class="ms-1" -->
|
||||
<!-- groups="uom.group_uom"/> -->
|
||||
<!-- </div> -->
|
||||
</ul>
|
||||
<!-- </ul> -->
|
||||
</div>
|
||||
|
||||
<!-- <button t-if="record._quantity == 0"-->
|
||||
<!-- <button
|
||||
id="add_quantity"
|
||||
class="btn btn-primary rounded-circle p-0 d-flex align-items-center justify-content-center"
|
||||
style="width: 25px; height: 25px;" type="object"
|
||||
name="add_quantity_button_so" string="ADD">
|
||||
<i class="fa fa-plus fs-5" title="إضافة"/>
|
||||
<div class="d-flex w-100 justify-content-center align-items-center mt-4">
|
||||
|
||||
</button> -->
|
||||
<button class="btn btn-secondary" type="button"
|
||||
name="add_quantity_button_so"
|
||||
data-name="add_quantity_button_request"
|
||||
title="إضافة منتج"
|
||||
onclick="return window.__dc_first_add(this);">
|
||||
<i class="fa fa-shopping-cart" />
|
||||
<span>Add</span>
|
||||
</button>
|
||||
|
||||
|
||||
<!-- <button-->
|
||||
<!-- id="add_quantity"-->
|
||||
<!-- class="oe_kanban_button oe_dynamic_button btn btn-primary rounded-circle p-0 d-flex align-items-center justify-content-center"-->
|
||||
<!-- style="width: 25px; height: 25px;" type="object"-->
|
||||
<!-- name="add_quantity_button_so" string="ADD">-->
|
||||
<!-- <i class="fa fa-plus fs-5" title="إضافة"/>-->
|
||||
<!-- </button>-->
|
||||
|
||||
<!-- <t t-if="record._quantity == 1">
|
||||
<span class="fa fa-plus fs-5">م الإضافة</span>
|
||||
</t> -->
|
||||
<!-- Quantity Controls: Minus, Display, Plus -->
|
||||
<div class="d-flex align-items-center gap-2 dc-qty-controls">
|
||||
<!-- Minus Button -->
|
||||
<button
|
||||
class="btn btn-light border rounded-circle p-0 d-flex align-items-center justify-content-center"
|
||||
style="width: 28px; height: 28px;"
|
||||
type="button"
|
||||
name="remove_quantity_button_so"
|
||||
title="تقليل الكمية"
|
||||
onclick="return window.__dc_remove(this);">
|
||||
<i class="fa fa-minus" style="font-size: 12px;"/>
|
||||
</button>
|
||||
<!-- Quantity Display -->
|
||||
<span class="badge bg-secondary px-2 py-1 dc-qty-badge"
|
||||
style="min-width: 35px; font-size: 14px; font-weight: bold;">
|
||||
<field name="_quantity"/>
|
||||
</span>
|
||||
<!-- Plus Button -->
|
||||
<button
|
||||
class="btn btn-primary rounded-circle p-0 d-flex align-items-center justify-content-center"
|
||||
style="width: 28px; height: 28px;"
|
||||
type="button"
|
||||
name="add_quantity_button_so"
|
||||
title="إضافة"
|
||||
onclick="return window.__dc_add(this);">
|
||||
<i class="fa fa-plus" style="font-size: 12px;"/>
|
||||
</button>
|
||||
<div class="dc-qty-controls d-none">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
name="remove_quantity_button_so"
|
||||
data-name="remove_quantity_button_so"
|
||||
title="تقليل الكمية"
|
||||
onclick="return window.__dc_remove(this);">
|
||||
<i class="fa fa-minus" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-control dc-qty-badge">
|
||||
<field name="_quantity" />
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
name="add_quantity_button_so"
|
||||
data-name="add_quantity_button_so"
|
||||
title="إضافة"
|
||||
onclick="return window.__dc_add(this);">
|
||||
<i class="fa fa-plus" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div name="_quantity" -->
|
||||
<!-- class="h-100 ml-2 d-flex align-items-center o_product_quantity o_field_widget o_quick_editable" -->
|
||||
<!-- style="z-index:1;align-items: center;"> -->
|
||||
<!-- <button id="remove_quantity" -->
|
||||
<!-- class="btn d-flex align-items-center justify-content-center o_qty_button btn-light text-muted" -->
|
||||
<!-- type="object" name="remove_quantity_button_so"> -->
|
||||
<!-- <i class="fa fa-minus center" title="Decrease" /> -->
|
||||
<!-- </button> -->
|
||||
<!-- <span style="font-size:1.5rem;" -->
|
||||
<!-- t-attf-class="{{record.id.value}}" -->
|
||||
<!-- onclick="change_input_so(this)"> -->
|
||||
<!-- <field name="_quantity"></field> -->
|
||||
<!-- </span> -->
|
||||
<!-- <button id="add_quantity" -->
|
||||
<!-- class="btn d-flex align-items-center justify-content-center o_qty_button btn-light text-muted" -->
|
||||
<!-- type="object" name="add_quantity_button_so" string="ADD"> -->
|
||||
<!-- <!– <i class="fa fa-plus" title="Increase" />–> -->
|
||||
<!-- </button> -->
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -119,6 +96,7 @@
|
|||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Tree view for product.template with sponsorship button -->
|
||||
<record id="view_product_template_tree_sponsorship" model="ir.ui.view">
|
||||
<field name="name">product.template.tree.sponsorship</field>
|
||||
|
|
@ -126,23 +104,24 @@
|
|||
<field name="arch" type="xml">
|
||||
<tree string="Products">
|
||||
<header>
|
||||
<button name="link_to_sponsorship" type="object" string="Link to Sponsorship" class="btn-primary"
|
||||
icon="fa-link"/>
|
||||
<button name="link_to_sponsorship" type="object" string="Link to Sponsorship"
|
||||
class="btn-primary"
|
||||
icon="fa-link" />
|
||||
</header>
|
||||
<field name="name"/>
|
||||
<field name="donation_category"/>
|
||||
<field name="list_price" string="Price"/>
|
||||
<field name="name" />
|
||||
<field name="donation_category" />
|
||||
<field name="list_price" string="Price" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="odex_takaful_product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">odex.takaful.product.template.form.view</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="uom_id" position="before">
|
||||
<field name="payment_method_id" options="{'no_create': True}"/>
|
||||
<field name="payment_method_id" options="{'no_create': True}" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue