forked from alaguraj/odoo-testing-addons
integrate Uber Direct delivery services into POS orders and add a channel management UI panel.
This commit is contained in:
parent
dae5dc5220
commit
2318ea10e8
@ -38,12 +38,17 @@ export class ChannelPanel extends Component {
|
|||||||
|
|
||||||
this.state = useState({
|
this.state = useState({
|
||||||
showDelivery: false,
|
showDelivery: false,
|
||||||
|
showDetails: false, // For manual fields toggle
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
searching: false,
|
searching: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleDetails() {
|
||||||
|
this.state.showDetails = !this.state.showDetails;
|
||||||
|
}
|
||||||
|
|
||||||
get currentOrder() {
|
get currentOrder() {
|
||||||
return this.pos.get_order();
|
return this.pos.get_order();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,20 +59,28 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Delivery Address Section -->
|
<!-- Delivery Address Section -->
|
||||||
<div t-if="isDelivery" class="delivery-panel p-2 rounded mt-1">
|
<div t-if="isDelivery" class="delivery-panel p-2 rounded mt-1 shadow-sm">
|
||||||
<div class="fw-bold small mb-2">🚚 Delivery Address</div>
|
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||||
|
<div class="fw-bold small text-muted"><i class="fa fa-map-marker text-danger"/> Delivery Address</div>
|
||||||
|
<button class="btn btn-sm btn-link text-primary p-0 text-decoration-none shadow-none fw-bold"
|
||||||
|
style="font-size: 10px"
|
||||||
|
t-on-click="toggleDetails">
|
||||||
|
<t t-if="state.showDetails"><i class="fa fa-caret-up"/> HIDE FIELDS</t>
|
||||||
|
<t t-else=""><i class="fa fa-caret-down"/> EDIT MANUAL</t>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Partner search -->
|
<!-- Partner search (always visible under Delivery) -->
|
||||||
<div class="position-relative mb-2">
|
<div class="position-relative mb-2">
|
||||||
<input type="text" class="form-control form-control-sm"
|
<input type="text" class="form-control form-control-sm border-primary"
|
||||||
placeholder="🔍 Search saved address..."
|
placeholder="🔍 Search saved address..."
|
||||||
t-att-value="state.searchQuery"
|
t-att-value="state.searchQuery"
|
||||||
t-on-input="onAddressSearch"/>
|
t-on-input="onAddressSearch"/>
|
||||||
<div t-if="state.searching" class="text-muted small ps-1">Searching...</div>
|
<div t-if="state.searching" class="text-muted small ps-1">Searching...</div>
|
||||||
<div t-if="state.searchResults.length > 0"
|
<div t-if="state.searchResults.length > 0"
|
||||||
class="address-dropdown position-absolute bg-white border rounded shadow-sm w-100">
|
class="address-dropdown position-absolute bg-white border rounded shadow w-100 mt-1">
|
||||||
<t t-foreach="state.searchResults" t-as="partner" t-key="partner.id">
|
<t t-foreach="state.searchResults" t-as="partner" t-key="partner.id">
|
||||||
<div class="address-result p-2 border-bottom small"
|
<div class="address-result p-2 border-bottom small list-group-item-action"
|
||||||
t-on-click="() => this.onSelectPartner(partner)">
|
t-on-click="() => this.onSelectPartner(partner)">
|
||||||
<span class="fw-bold" t-esc="partner.name"/> —
|
<span class="fw-bold" t-esc="partner.name"/> —
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
@ -83,7 +91,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Manual fields -->
|
<!-- Manual fields (hidden by default) -->
|
||||||
|
<div t-if="state.showDetails" class="manual-address-fields mt-2 p-2 border-top bg-white rounded">
|
||||||
<input type="text" class="form-control form-control-sm mb-1"
|
<input type="text" class="form-control form-control-sm mb-1"
|
||||||
placeholder="Street"
|
placeholder="Street"
|
||||||
t-att-value="currentOrder.delivery_street"
|
t-att-value="currentOrder.delivery_street"
|
||||||
@ -108,6 +117,14 @@
|
|||||||
t-on-change="(ev) => this.onDeliveryFieldChange('notes', ev)"/>
|
t-on-change="(ev) => this.onDeliveryFieldChange('notes', ev)"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Info when hidden -->
|
||||||
|
<div t-if="!state.showDetails && currentOrder.delivery_street" class="small mt-1 text-muted fst-italic">
|
||||||
|
<i class="fa fa-info-circle"/>
|
||||||
|
<t t-esc="currentOrder.delivery_street"/>,
|
||||||
|
<t t-esc="currentOrder.delivery_city"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
|
|||||||
@ -158,8 +158,21 @@ class PosOrder(models.Model):
|
|||||||
order._add_uber_delivery_fee(delivery_fee)
|
order._add_uber_delivery_fee(delivery_fee)
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as e:
|
except requests.exceptions.HTTPError as e:
|
||||||
error_msg = f"Uber API Error {e.response.status_code}: {e.response.text}"
|
# Try to parse the error message if it's JSON
|
||||||
raise UserError(_(error_msg))
|
try:
|
||||||
|
err_data = e.response.json()
|
||||||
|
err_code = err_data.get('code', 'unknown_error')
|
||||||
|
err_msg = err_data.get('message', 'An error occurred with Uber API.')
|
||||||
|
|
||||||
|
if err_code == 'address_undeliverable':
|
||||||
|
# Special handling for radius errors (most common issue)
|
||||||
|
details = err_data.get('metadata', {}).get('details', '')
|
||||||
|
raise UserError(_("Address Undeliverable: The drop-off location is outside Uber's delivery radius. \n\nDetails: %s") % details)
|
||||||
|
|
||||||
|
raise UserError(_("Uber API Error (%s): %s") % (err_code, err_msg))
|
||||||
|
except (ValueError, AttributeError):
|
||||||
|
# Fallback to default error text if not JSON
|
||||||
|
raise UserError(_("Uber API Error %s: %s") % (e.response.status_code, e.response.text))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise UserError(_("Failed to request delivery: %s") % str(e))
|
raise UserError(_("Failed to request delivery: %s") % str(e))
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user