Eliminate Python dependency: embed frontend assets in odoo-go
- 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>
This commit is contained in:
66
frontend/stock/static/src/widgets/forecast_widget.js
Normal file
66
frontend/stock/static/src/widgets/forecast_widget.js
Normal file
@@ -0,0 +1,66 @@
|
||||
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);
|
||||
Reference in New Issue
Block a user