- Copy all OWL frontend assets (JS/CSS/XML/fonts/images) into frontend/ directory (2925 files, 43MB) — no more runtime reads from Python Odoo - Replace OdooAddonsPath config with FrontendDir pointing to local frontend/ - Rewire bundle.go, static.go, templates.go, webclient.go to read from frontend/ instead of external Python Odoo addons directory - Auto-detect frontend/ and build/ dirs relative to binary in main.go - Delete obsolete Python helper scripts (tools/*.py) The Go server is now fully self-contained: single binary + frontend/ folder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
67 lines
2.4 KiB
JavaScript
67 lines
2.4 KiB
JavaScript
import { FloatField, floatField } from "@web/views/fields/float/float_field";
|
|
import { formatDate } from "@web/core/l10n/dates";
|
|
import { formatFloat } from "@web/views/fields/formatters";
|
|
import { registry } from "@web/core/registry";
|
|
import { useService } from "@web/core/utils/hooks";
|
|
|
|
export class ForecastWidgetField extends FloatField {
|
|
static template = "stock.ForecastWidget";
|
|
setup() {
|
|
const { data, fields, resId } = this.props.record;
|
|
this.actionService = useService("action");
|
|
this.orm = useService("orm");
|
|
this.resId = resId;
|
|
|
|
this.forecastExpectedDate = formatDate(
|
|
data.forecast_expected_date,
|
|
fields.forecast_expected_date
|
|
);
|
|
if (data.forecast_expected_date && data.date_deadline) {
|
|
this.forecastIsLate = data.forecast_expected_date > data.date_deadline;
|
|
}
|
|
const digits = fields.forecast_availability.digits;
|
|
const options = { digits, thousandsSep: "", decimalPoint: "." };
|
|
const forecast_availability = parseFloat(formatFloat(data.forecast_availability, options));
|
|
const product_qty = parseFloat(formatFloat(data.product_qty, options));
|
|
this.willBeFulfilled = forecast_availability >= product_qty;
|
|
this.state = data.state;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Handlers
|
|
//--------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Opens the Forecast Report for the `stock.move` product.
|
|
*/
|
|
async _openReport(ev) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
if (!this.resId || !this.props.record.data.is_storable) {
|
|
return;
|
|
}
|
|
const action = await this.orm.call("stock.move", "action_product_forecast_report", [
|
|
this.resId,
|
|
]);
|
|
this.actionService.doAction(action);
|
|
}
|
|
|
|
get decoration() {
|
|
if (!this.forecastExpectedDate && this.willBeFulfilled){
|
|
return "text-bg-success"
|
|
} else if (this.forecastExpectedDate && this.willBeFulfilled){
|
|
return this.forecastIsLate ? 'text-bg-danger' : 'text-bg-warning'
|
|
} else {
|
|
return 'text-bg-danger'
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
export const forecastWidgetField = {
|
|
...floatField,
|
|
component: ForecastWidgetField,
|
|
};
|
|
|
|
registry.category("fields").add("forecast_widget", forecastWidgetField);
|