[IMP] point_of_sale: add date picker to ship later option
In order to plan a certain Ship Later pos order, a user must go to the backend and find the correct picking linked to the order he made. The date picker can be useful to not have to go back to the backend and continue selling to customers. Now, when pushing on the button Ship Later, a date picker appears with a default date set as the current date and the user can chose another date after the default date. closes odoo/odoo#107115 Task-id: 3078526 Related: odoo/upgrade#4200 Signed-off-by: Trinh Jacky (trj) <trj@odoo.com>
This commit is contained in:
@@ -52,7 +52,7 @@ class PosOrder(models.Model):
|
||||
'amount_return': ui_order['amount_return'],
|
||||
'company_id': self.env['pos.session'].browse(ui_order['pos_session_id']).company_id.id,
|
||||
'to_invoice': ui_order['to_invoice'] if "to_invoice" in ui_order else False,
|
||||
'to_ship': ui_order['to_ship'] if "to_ship" in ui_order else False,
|
||||
'shipping_date': ui_order['shipping_date'] if "shipping_date" in ui_order else False,
|
||||
'is_tipped': ui_order.get('is_tipped', False),
|
||||
'tip_amount': ui_order.get('tip_amount', 0),
|
||||
'access_token': ui_order.get('access_token', '')
|
||||
@@ -284,7 +284,7 @@ class PosOrder(models.Model):
|
||||
payment_ids = fields.One2many('pos.payment', 'pos_order_id', string='Payments', readonly=True)
|
||||
session_move_id = fields.Many2one('account.move', string='Session Journal Entry', related='session_id.move_id', readonly=True, copy=False)
|
||||
to_invoice = fields.Boolean('To invoice', copy=False)
|
||||
to_ship = fields.Boolean('To ship')
|
||||
shipping_date = fields.Date('Shipping Date')
|
||||
is_invoiced = fields.Boolean('Is Invoiced', compute='_compute_is_invoiced')
|
||||
is_tipped = fields.Boolean('Is this already tipped?', readonly=True)
|
||||
tip_amount = fields.Float(string='Tip Amount', digits=0, readonly=True)
|
||||
@@ -887,7 +887,7 @@ class PosOrder(models.Model):
|
||||
|
||||
def _create_order_picking(self):
|
||||
self.ensure_one()
|
||||
if self.to_ship:
|
||||
if self.shipping_date:
|
||||
self.lines._launch_stock_rule_from_pos_order_lines()
|
||||
else:
|
||||
if self._should_create_picking_real_time():
|
||||
@@ -1028,7 +1028,7 @@ class PosOrder(models.Model):
|
||||
'creation_date': order.date_order.astimezone(timezone),
|
||||
'fiscal_position_id': order.fiscal_position_id.id,
|
||||
'to_invoice': order.to_invoice,
|
||||
'to_ship': order.to_ship,
|
||||
'shipping_date': order.shipping_date,
|
||||
'state': order.state,
|
||||
'account_move': order.account_move.id,
|
||||
'id': order.id,
|
||||
@@ -1238,7 +1238,11 @@ class PosOrderLine(models.Model):
|
||||
"""
|
||||
self.ensure_one()
|
||||
# Use the delivery date if there is else use date_order and lead time
|
||||
date_deadline = self.order_id.date_order
|
||||
if self.order_id.shipping_date:
|
||||
date_deadline = self.order_id.shipping_date
|
||||
else:
|
||||
date_deadline = self.order_id.date_order
|
||||
|
||||
values = {
|
||||
'group_id': group_id,
|
||||
'date_planned': date_deadline,
|
||||
|
||||
@@ -587,7 +587,7 @@ class PosSession(models.Model):
|
||||
session_destination_id = picking_type.default_location_dest_id.id
|
||||
|
||||
for order in self.order_ids:
|
||||
if order.company_id.anglo_saxon_accounting and order.is_invoiced or order.to_ship:
|
||||
if order.company_id.anglo_saxon_accounting and order.is_invoiced or order.shipping_date:
|
||||
continue
|
||||
destination_id = order.partner_id.property_stock_customer.id or session_destination_id
|
||||
if destination_id in lines_grouped_by_dest_location:
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import AbstractAwaitablePopup from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
|
||||
import Registries from "@point_of_sale/js/Registries";
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
|
||||
const { onMounted, useRef, useState } = owl;
|
||||
|
||||
class DatePickerPopup extends AbstractAwaitablePopup {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.state = useState({shippingDate: this._today()});
|
||||
this.inputRef = useRef('input');
|
||||
onMounted(() => this.inputRef.el.focus());
|
||||
}
|
||||
getPayload() {
|
||||
return this.state.shippingDate < this._today() ? this._today(): this.state.shippingDate;
|
||||
}
|
||||
_today() {
|
||||
return new Date().toISOString().split('T')[0]
|
||||
}
|
||||
|
||||
}
|
||||
DatePickerPopup.template = 'DatePickerPopup';
|
||||
DatePickerPopup.defaultProps = {
|
||||
confirmText: _lt('Confirm'),
|
||||
cancelText: _lt('Discard'),
|
||||
title: _lt('DatePicker'),
|
||||
};
|
||||
|
||||
Registries.Component.add(DatePickerPopup);
|
||||
|
||||
export default DatePickerPopup;
|
||||
@@ -138,10 +138,17 @@ class PaymentScreen extends PosComponent {
|
||||
this.currentOrder.set_tip(parse.float(payload));
|
||||
}
|
||||
}
|
||||
toggleIsToShip() {
|
||||
// click_ship
|
||||
this.currentOrder.set_to_ship(!this.currentOrder.is_to_ship());
|
||||
this.render(true);
|
||||
async toggleShippingDatePicker() {
|
||||
if (!this.currentOrder.getShippingDate()) {
|
||||
const { confirmed, payload: shippingDate } = await this.showPopup("DatePickerPopup", {
|
||||
title: this.env._t("Select the shipping date"),
|
||||
});
|
||||
if (confirmed) {
|
||||
this.currentOrder.setShippingDate(shippingDate);
|
||||
}
|
||||
} else {
|
||||
this.currentOrder.setShippingDate(false);
|
||||
}
|
||||
}
|
||||
deletePaymentLine(event) {
|
||||
var self = this;
|
||||
@@ -326,7 +333,7 @@ class PaymentScreen extends PosComponent {
|
||||
}
|
||||
|
||||
if (
|
||||
(this.currentOrder.is_to_invoice() || this.currentOrder.is_to_ship()) &&
|
||||
(this.currentOrder.is_to_invoice() || this.currentOrder.getShippingDate()) &&
|
||||
!this.currentOrder.get_partner()
|
||||
) {
|
||||
const { confirmed } = await this.showPopup("ConfirmPopup", {
|
||||
@@ -343,7 +350,7 @@ class PaymentScreen extends PosComponent {
|
||||
|
||||
const partner = this.currentOrder.get_partner();
|
||||
if (
|
||||
this.currentOrder.is_to_ship() &&
|
||||
this.currentOrder.getShippingDate() &&
|
||||
!(partner.name && partner.street && partner.city && partner.country_id)
|
||||
) {
|
||||
this.showPopup("ErrorPopup", {
|
||||
|
||||
@@ -29,6 +29,9 @@ class OrderReceipt extends PosComponent {
|
||||
get receiptEnv() {
|
||||
return this._receiptEnv;
|
||||
}
|
||||
get shippingDate() {
|
||||
return this.receiptEnv.shippingDate
|
||||
}
|
||||
isSimple(line) {
|
||||
return (
|
||||
line.discount === 0 &&
|
||||
|
||||
@@ -2496,6 +2496,7 @@ export class Order extends PosModel {
|
||||
this.cashier = this.pos.get_cashier();
|
||||
this.finalized = false; // if true, cannot be modified.
|
||||
this.set_pricelist(this.pos.default_pricelist);
|
||||
this.shippingDate = null;
|
||||
|
||||
this.partner = null;
|
||||
|
||||
@@ -2591,9 +2592,9 @@ export class Order extends PosModel {
|
||||
}
|
||||
this.set_partner(partner);
|
||||
|
||||
this.temporary = false; // FIXME
|
||||
this.to_invoice = false; // FIXME
|
||||
this.to_ship = false;
|
||||
this.temporary = false; // FIXME
|
||||
this.to_invoice = false; // FIXME
|
||||
this.shippingDate = json.shipping_date;
|
||||
|
||||
var orderlines = json.lines;
|
||||
for (var i = 0; i < orderlines.length; i++) {
|
||||
@@ -2659,7 +2660,7 @@ export class Order extends PosModel {
|
||||
fiscal_position_id: this.fiscal_position ? this.fiscal_position.id : false,
|
||||
server_id: this.server_id ? this.server_id : false,
|
||||
to_invoice: this.to_invoice ? this.to_invoice : false,
|
||||
to_ship: this.to_ship ? this.to_ship : false,
|
||||
shipping_date: this.shippingDate ? this.shippingDate : false,
|
||||
is_tipped: this.is_tipped || false,
|
||||
tip_amount: this.tip_amount || 0,
|
||||
access_token: this.access_token || "",
|
||||
@@ -2669,6 +2670,16 @@ export class Order extends PosModel {
|
||||
}
|
||||
return json;
|
||||
}
|
||||
_exportShippingDateForPrinting() {
|
||||
const shippingDate = new Date(this.shippingDate);
|
||||
const localeShippingDate = field_utils.format.date(
|
||||
moment(shippingDate), {}, {timezone: false});
|
||||
const exportedDate = {
|
||||
localestring: localeShippingDate,
|
||||
validationDate: shippingDate,
|
||||
};
|
||||
return exportedDate;
|
||||
}
|
||||
export_for_printing() {
|
||||
var orderlines = [];
|
||||
var self = this;
|
||||
@@ -3536,6 +3547,7 @@ export class Order extends PosModel {
|
||||
receipt: this.export_for_printing(),
|
||||
orderlines: this.get_orderlines(),
|
||||
paymentlines: this.get_paymentlines(),
|
||||
shippingDate: this.shippingDate ? this._exportShippingDateForPrinting() : false,
|
||||
};
|
||||
}
|
||||
updatePricelist(newPartner) {
|
||||
@@ -3561,12 +3573,11 @@ export class Order extends PosModel {
|
||||
this.set_pricelist(newPartnerPricelist);
|
||||
}
|
||||
/* ---- Ship later --- */
|
||||
set_to_ship(to_ship) {
|
||||
this.assert_editable();
|
||||
this.to_ship = to_ship;
|
||||
setShippingDate(shippingDate) {
|
||||
this.shippingDate = shippingDate
|
||||
}
|
||||
is_to_ship() {
|
||||
return this.to_ship;
|
||||
getShippingDate() {
|
||||
return this.shippingDate;
|
||||
}
|
||||
getHasRefundLines() {
|
||||
for (const line of this.get_orderlines()) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="DatePickerPopup" owl="1">
|
||||
<div class="popup">
|
||||
<header class="title">
|
||||
<t t-esc="props.title" />
|
||||
</header>
|
||||
<main>
|
||||
<input type="date" t-model="state.shippingDate" t-ref="input" t-att-min="_today()"/>
|
||||
</main>
|
||||
<div class="footer footer-flex">
|
||||
<div class="button confirm highlight" t-on-click="confirm">
|
||||
<t t-esc="props.confirmText" />
|
||||
</div>
|
||||
<div class="button cancel" t-on-click="cancel">
|
||||
<t t-esc="props.cancelText" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -90,9 +90,12 @@
|
||||
<i class="fa fa-archive" /> Open Cashbox
|
||||
</div>
|
||||
<div t-if="env.pos.config.ship_later" class="button"
|
||||
t-att-class="{ highlight: currentOrder.is_to_ship() }"
|
||||
t-on-click="toggleIsToShip">
|
||||
t-att-class="{ highlight: currentOrder.getShippingDate() }"
|
||||
t-on-click="toggleShippingDatePicker">
|
||||
<i class="fa fa-clock-o" /> Ship Later
|
||||
<span t-if="currentOrder.getShippingDate()">
|
||||
(<t t-esc="currentOrder.getShippingDate()"/>)
|
||||
<span/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -153,6 +153,19 @@
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<t t-if="shippingDate">
|
||||
<div class="pos-receipt-order-data">
|
||||
Expected delivery:
|
||||
<t t-if="shippingDate.localestring">
|
||||
<div><t t-esc="shippingDate.localestring" /></div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div><t t-esc="shippingDate.validationDate" /></div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<br/>
|
||||
<div class="pos-receipt-order-data">
|
||||
<div><t t-esc="receipt.name" /></div>
|
||||
|
||||
@@ -1040,7 +1040,7 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon):
|
||||
'amount_total': untax+tax,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
'to_ship': True,
|
||||
'shipping_date': fields.Date.today(),
|
||||
})
|
||||
|
||||
context_make_payment = {
|
||||
|
||||
@@ -86,6 +86,7 @@ class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentToOrderSc
|
||||
if (confirmed) {
|
||||
const currentPOSOrder = this.env.pos.get_order();
|
||||
const sale_order = await this._getSaleOrder(clickedOrder.id);
|
||||
clickedOrder.shipping_date = sale_order.shipping_date
|
||||
try {
|
||||
await this.env.pos.load_new_partners();
|
||||
} catch {
|
||||
@@ -293,6 +294,7 @@ class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentToOrderSc
|
||||
"fiscal_position_id",
|
||||
"amount_total",
|
||||
"amount_untaxed",
|
||||
"picking_ids",
|
||||
],
|
||||
],
|
||||
context: this.env.session.user_context,
|
||||
@@ -300,6 +302,16 @@ class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentToOrderSc
|
||||
|
||||
const sale_lines = await this._getSOLines(sale_order[0].order_line);
|
||||
sale_order[0].order_line = sale_lines;
|
||||
|
||||
const picking_id = await this.rpc({
|
||||
model: 'stock.picking',
|
||||
method: 'read',
|
||||
args: [
|
||||
[sale_order[0].picking_ids[0]],
|
||||
['scheduled_date'],
|
||||
],
|
||||
});
|
||||
sale_order[0].shipping_date = picking_id[0].scheduled_date;
|
||||
|
||||
return sale_order[0];
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ const PosSaleOrderline = (Orderline) =>
|
||||
this.sale_order_line_id = this.sale_order_line_id || options.sale_order_line_id;
|
||||
this.down_payment_details = this.down_payment_details || options.down_payment_details;
|
||||
this.customerNote = this.customerNote || options.customer_note;
|
||||
if (this.sale_order_origin_id && this.sale_order_origin_id.shipping_date) {
|
||||
this.order.setShippingDate(this.sale_order_origin_id.shipping_date);
|
||||
}
|
||||
}
|
||||
init_from_JSON(json) {
|
||||
super.init_from_JSON(...arguments);
|
||||
|
||||
Reference in New Issue
Block a user