integrate Uber Direct delivery services into POS orders and add a channel management UI panel.

This commit is contained in:
Alaguraj0361 2026-04-02 22:27:48 +05:30
parent dae5dc5220
commit 2318ea10e8
3 changed files with 65 additions and 30 deletions

View File

@ -38,12 +38,17 @@ export class ChannelPanel extends Component {
this.state = useState({
showDelivery: false,
showDetails: false, // For manual fields toggle
searchQuery: '',
searchResults: [],
searching: false,
});
}
toggleDetails() {
this.state.showDetails = !this.state.showDetails;
}
get currentOrder() {
return this.pos.get_order();
}

View File

@ -59,20 +59,28 @@
</div>
<!-- Delivery Address Section -->
<div t-if="isDelivery" class="delivery-panel p-2 rounded mt-1">
<div class="fw-bold small mb-2">🚚 Delivery Address</div>
<div t-if="isDelivery" class="delivery-panel p-2 rounded mt-1 shadow-sm">
<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">
<input type="text" class="form-control form-control-sm"
<input type="text" class="form-control form-control-sm border-primary"
placeholder="🔍 Search saved address..."
t-att-value="state.searchQuery"
t-on-input="onAddressSearch"/>
<div t-if="state.searching" class="text-muted small ps-1">Searching...</div>
<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">
<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)">
<span class="fw-bold" t-esc="partner.name"/>
<span class="text-muted">
@ -83,29 +91,38 @@
</div>
</div>
<!-- Manual fields -->
<input type="text" class="form-control form-control-sm mb-1"
placeholder="Street"
t-att-value="currentOrder.delivery_street"
t-on-change="(ev) => this.onDeliveryFieldChange('street', ev)"/>
<div class="d-flex gap-1 mb-1">
<input type="text" class="form-control form-control-sm"
placeholder="City"
t-att-value="currentOrder.delivery_city"
t-on-change="(ev) => this.onDeliveryFieldChange('city', ev)"/>
<input type="text" class="form-control form-control-sm"
placeholder="Zip" style="max-width:90px"
t-att-value="currentOrder.delivery_zip"
t-on-change="(ev) => this.onDeliveryFieldChange('zip', ev)"/>
<!-- 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"
placeholder="Street"
t-att-value="currentOrder.delivery_street"
t-on-change="(ev) => this.onDeliveryFieldChange('street', ev)"/>
<div class="d-flex gap-1 mb-1">
<input type="text" class="form-control form-control-sm"
placeholder="City"
t-att-value="currentOrder.delivery_city"
t-on-change="(ev) => this.onDeliveryFieldChange('city', ev)"/>
<input type="text" class="form-control form-control-sm"
placeholder="Zip" style="max-width:90px"
t-att-value="currentOrder.delivery_zip"
t-on-change="(ev) => this.onDeliveryFieldChange('zip', ev)"/>
</div>
<input type="tel" class="form-control form-control-sm mb-1"
placeholder="Phone"
t-att-value="currentOrder.delivery_phone"
t-on-change="(ev) => this.onDeliveryFieldChange('phone', ev)"/>
<textarea class="form-control form-control-sm" rows="2"
placeholder="Delivery notes (gate code, floor...)"
t-att-value="currentOrder.delivery_notes"
t-on-change="(ev) => this.onDeliveryFieldChange('notes', ev)"/>
</div>
<!-- Quick Info when hidden -->
<div t-if="!state.showDetails &amp;&amp; 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>
<input type="tel" class="form-control form-control-sm mb-1"
placeholder="Phone"
t-att-value="currentOrder.delivery_phone"
t-on-change="(ev) => this.onDeliveryFieldChange('phone', ev)"/>
<textarea class="form-control form-control-sm" rows="2"
placeholder="Delivery notes (gate code, floor...)"
t-att-value="currentOrder.delivery_notes"
t-on-change="(ev) => this.onDeliveryFieldChange('notes', ev)"/>
</div>
</div>

View File

@ -158,8 +158,21 @@ class PosOrder(models.Model):
order._add_uber_delivery_fee(delivery_fee)
except requests.exceptions.HTTPError as e:
error_msg = f"Uber API Error {e.response.status_code}: {e.response.text}"
raise UserError(_(error_msg))
# Try to parse the error message if it's JSON
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:
raise UserError(_("Failed to request delivery: %s") % str(e))