mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 21:12:06 +02:00
Initial commit: Sale packages
This commit is contained in:
commit
14e3d26998
6469 changed files with 2479670 additions and 0 deletions
|
|
@ -0,0 +1,92 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { formatDateTime } from "@web/core/l10n/dates";
|
||||
import { localization } from "@web/core/l10n/localization";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { usePopover } from "@web/core/popover/popover_hook";
|
||||
|
||||
const { Component, EventBus, onWillRender } = owl;
|
||||
|
||||
export class QtyAtDatePopover extends Component {
|
||||
setup() {
|
||||
this.actionService = useService("action");
|
||||
}
|
||||
|
||||
openForecast() {
|
||||
this.actionService.doAction("stock.stock_replenishment_product_product_action", {
|
||||
additionalContext: {
|
||||
active_model: 'product.product',
|
||||
active_id: this.props.record.data.product_id[0],
|
||||
warehouse: this.props.record.data.warehouse_id && this.props.record.data.warehouse_id[0],
|
||||
move_to_match_ids: this.props.record.data.move_ids.records.map(record => record.data.id),
|
||||
sale_line_to_match_id: this.props.record.data.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
QtyAtDatePopover.template = "sale_stock.QtyDetailPopOver";
|
||||
|
||||
export class QtyAtDateWidget extends Component {
|
||||
setup() {
|
||||
this.bus = new EventBus();
|
||||
this.popover = usePopover();
|
||||
this.closePopover = null;
|
||||
this.calcData = {};
|
||||
onWillRender(() => {
|
||||
this.initCalcData();
|
||||
})
|
||||
}
|
||||
|
||||
initCalcData() {
|
||||
// calculate data not in record
|
||||
const { data } = this.props.record;
|
||||
if (data.scheduled_date) {
|
||||
// TODO: might need some round_decimals to avoid errors
|
||||
if (data.state === 'sale') {
|
||||
this.calcData.will_be_fulfilled = data.free_qty_today >= data.qty_to_deliver;
|
||||
} else {
|
||||
this.calcData.will_be_fulfilled = data.virtual_available_at_date >= data.qty_to_deliver;
|
||||
}
|
||||
this.calcData.will_be_late = data.forecast_expected_date && data.forecast_expected_date > data.scheduled_date;
|
||||
if (['draft', 'sent'].includes(data.state)) {
|
||||
// Moves aren't created yet, then the forecasted is only based on virtual_available of quant
|
||||
this.calcData.forecasted_issue = !this.calcData.will_be_fulfilled && !data.is_mto;
|
||||
} else {
|
||||
// Moves are created, using the forecasted data of related moves
|
||||
this.calcData.forecasted_issue = !this.calcData.will_be_fulfilled || this.calcData.will_be_late;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateCalcData() {
|
||||
// popup specific data
|
||||
const { data } = this.props.record;
|
||||
if (!data.scheduled_date) {
|
||||
return;
|
||||
}
|
||||
this.calcData.delivery_date = formatDateTime(data.scheduled_date, { format: localization.dateFormat });
|
||||
if (data.forecast_expected_date) {
|
||||
this.calcData.forecast_expected_date_str = formatDateTime(data.forecast_expected_date, { format: localization.dateFormat });
|
||||
}
|
||||
}
|
||||
|
||||
showPopup(ev) {
|
||||
this.updateCalcData();
|
||||
this.closePopover = this.popover.add(
|
||||
ev.currentTarget,
|
||||
this.constructor.components.Popover,
|
||||
{bus: this.bus, record: this.props.record, calcData: this.calcData},
|
||||
{
|
||||
position: 'top',
|
||||
}
|
||||
);
|
||||
this.bus.addEventListener('close-popover', this.closePopover);
|
||||
}
|
||||
}
|
||||
|
||||
QtyAtDateWidget.components = { Popover: QtyAtDatePopover };
|
||||
QtyAtDateWidget.template = "sale_stock.qtyAtDate";
|
||||
|
||||
registry.category("view_widgets").add("qty_at_date_widget", QtyAtDateWidget);
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<template id="template" xml:space="preserve">
|
||||
|
||||
<!-- TODO: rename this to QtyAtDate in master version -->
|
||||
<t t-name="sale_stock.qtyAtDate" owl="1">
|
||||
<div t-att-class="!props.record.data.display_qty_widget ? 'invisible' : ''">
|
||||
<a t-att-tabindex="props.record.data.display_qty_widget ? '0' : '-1'" t-on-click="showPopup" t-attf-class="fa fa-area-chart {{ calcData.forecasted_issue ? 'text-danger' : 'text-primary' }}"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- TODO: rename this to QtyAtDatePopup in master version -->
|
||||
<t t-name="sale_stock.QtyDetailPopOver" owl="1">
|
||||
<div>
|
||||
<h6>Availability</h6>
|
||||
<table class="table table-borderless table-sm">
|
||||
<tbody>
|
||||
<t t-if="!props.record.data.is_mto and ['draft', 'sent'].includes(props.record.data.state)">
|
||||
<tr>
|
||||
<td><strong>Forecasted Stock</strong><br/><small>On <span t-out="props.calcData.delivery_date"/></small></td>
|
||||
<td><b t-out='props.record.data.virtual_available_at_date'/> <t t-out='props.record.data.product_uom[1]'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Available</strong><br /><small>All planned operations included</small></td>
|
||||
<td><b t-out='props.record.data.free_qty_today' t-att-class="!props.calcData.will_be_fulfilled ? 'text-danger': ''"/> <t t-out='props.record.data.product_uom[1]'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<t t-elif="props.record.data.is_mto and ['draft', 'sent'].includes(props.record.data.state)">
|
||||
<tr>
|
||||
<td><strong>Expected Delivery</strong></td>
|
||||
<td class="oe-right"><span t-out="props.calcData.delivery_date"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<p>This product is replenished on demand.</p>
|
||||
</tr>
|
||||
</t>
|
||||
<t t-elif="props.record.data.state == 'sale'">
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Reserved</strong><br/>
|
||||
</td>
|
||||
<td style="min-width: 50px; text-align: right;">
|
||||
<b t-out='props.record.data.qty_available_today'/> <t t-out='props.record.data.product_uom[1]'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="props.record.data.qty_available_today < props.record.data.qty_to_deliver">
|
||||
<td>
|
||||
<span t-if="props.calcData.will_be_fulfilled and props.calcData.forecast_expected_date_str">
|
||||
Remaining demand available at <b t-out="props.calcData.forecast_expected_date_str" t-att-class="props.record.data.scheduled_date < props.record.data.forecast_expected_date ? 'text-danger' : ''"/>
|
||||
</span>
|
||||
<span t-elif="!props.calcData.will_be_fulfilled and props.calcData.forecast_expected_date_str" class="text-danger">
|
||||
Not enough future availability
|
||||
</span>
|
||||
<span t-elif="!props.calcData.will_be_fulfilled" class="text-danger">
|
||||
No future availability
|
||||
</span>
|
||||
<span t-else="">
|
||||
Available in stock
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
<button t-if="!props.record.data.is_mto" class="text-start btn btn-link"
|
||||
type="button" t-on-click="openForecast">
|
||||
<i class="fa fa-fw o_button_icon fa-arrow-right"></i>
|
||||
View Forecast
|
||||
</button>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue