Extending PoS Module Odoo 8.x (formely OpenERP) ? - odoo

I need to make some customizations in the PoS module in Odoo 8.
For this i have created a module call "cus_pos". With this code i extended the interface:
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-extend="PosWidget">
<t t-jquery="div.pos-leftpane > div.window > div:last" t-operation="after">
<div class="payment-lines">
<div class="paymentline selected">
<!-- trigger an error <t t-esc="widget.get_list_salespersons()" /> -->
<div class="paymentline-name"> Salesperson: </div>
<select id="salesperson-select" class="paymentline-input">
</select>
</div>
</div>
</t>
</t>
</templates>
But when i try to extend the widget "PosWidget", to add a method to populate the select "salesperson-select", i get this error "Error: QWeb2 - template['PosWidget']: Runtime Error: TypeError: dict.widget.get_list_salespersons is not a function".
To extend the "PosWidget" i had tried this strategies:
One:
openerp.cus_pos = function(instance) {
template: 'PosWidget',
var module = instance.point_of_sale;
module.PosWidget = module.PosWidget.extend({
get_list_salespersons: function() {
console.log("Hurray!!!");
}
});
}
Two:
function openerp_pos_salesperson(instance, module) { //module is instance.point_of_sale
var module = instance.point_of_sale;
var QWeb = instance.web.qweb;
_t = instance.web._t;
module.SalePersonWidget = module.PosWidget.include({
template: 'PosWidget',
get_list_salespersons: function() {
console.log("Hurray!!!");
}
});
}
Three:
function openerp_pos_saleperson(instance, module) { //module is instance.point_of_sale
var module = instance.point_of_sale;
var QWeb = instance.web.qweb;
_t = instance.web._t;
module.SalePersonWidget = module.PosWidget.include({
template: 'PosWidget',
get_list_salespersons: function() {
console.log("Hurray!!!");
}
});
}
(function() {
var _super = window.openerp.point_of_sale;
window.openerp.point_of_sale = function(instance) {
_super(instance);
var module = instance.point_of_sale;
openerp_pos_vendedor(instance,module);
}
})();
Four:
openerp.cus_pos = function(instance) {
var module = instance.point_of_sale;
var _super_ = module.PosWidget.prototype.get_list_salespersons;
module.PosWidget.prototype.get_list_salespersons = function() {
console.log("Hurray!!!");
_super_.call(this);
};
};
Searching for some documentation i found http://thierry-godin.developpez.com/openerp/tutorial-module-creation-pos-modification-english-version/#LI but is outdated.
Any help on my question would be a great help. Many Thanks

Yes Thierry Godin wrote things about V7, but a lot of things are obsolete now in V8.
you should check new V8 modules in OCA on gitHub / OCA / POS
You can too take a look on the Odoo Forum.
After that, if you're still blocked I can check your problem.
There is 2 ways to overload existing Odoo POS :
https://github.com/OCA/pos/blob/8.0/pos_product_template/static/src/js/ppt.js#L74
https://github.com/OCA/pos/blob/8.0/pos_product_template/static/src/js/ppt.js#L109
(It depends of the kind of objects.)
BTW, what is the objective of your module ?
Kind regards.

Related

Vue-Select: Pushing a 2 dimensional array to :options

The plugin Vue-Select.
What I was trying to do is, make a search-select-dropdown input based on database.
So here's my SQL first named Ms_Location.
id_Loc | name_Loc
LOC0001 | Indonesia
LOC0002 | China
LOC0003 | America
My index.php
<!DOCTYPE html>
<html>
<head>
</head
<body>
<div class="form-group">
<label for="lokasi_id" class="control-label required"><strong>Lokasi</strong></label>
<v-select :options="lokasi_list" placeholder='Type location..'></v-select>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script src="https://unpkg.com/vue-select#latest"></script>
Vue.component('v-select', VueSelect.VueSelect);
var app = new Vue ({
el: '#app',
data: {
lokasi_select: '',
lokasi_list: [],
},
// End of data
computed: {
get_lokasi() {
var list_loc = new Array();
list_loc = <?php include('receive_lokasi.php') ?>;
for(var i=0; i<list_loc.length; i++) {
var pushLoc = {
label: list_loc[i][1], value: list_loc[i][0]
}
this.lokasi_list.push(pushLoc);
}
return list_loc[0][1];
}
}
})
});
</script>
</body>
</html>
And this is my receive_lokasi.php
<?php
include ('koneksi.php');
$condition = "1";
if(isset($_GET['userid'])){
$condition = " id=".$_GET['userid'];
}
$sqltran = mysqli_query($con, "SELECT id_Loc, name_Loc FROM ms_location")or die(mysqli_error($con));
$response = array();
while ($rowList = mysqli_fetch_array($sqltran,MYSQLI_NUM)) {
$response[] = $rowList;
}
echo json_encode($response);
mysqli_close($con);
?>
However, I can't seem to get the option shown. This only happens after I make the get_lokasi(). So the mistake is probably there? Or perhaps I was missing something.
I've tried to print the lokasi_list somewhere, and yes, the value is there, but not shown in the dropdown bar.
Also, I'm new to Vue, so any help would be good. Thanks!
Nevermind..
My mistake, I didn't notice my receive_lokasi.php code
Instead of using MYSQLI_NUM
while ($rowList = mysqli_fetch_array($sqltran,MYSQLI_NUM)) {
$response[] = $rowList;
}
I should be using MYSQLI_ASSOC, as documented in here.
while ($rowList = mysqli_fetch_array($sqltran,**MYSQLI_ASSOC**)) {
$response[] = $rowList;
}
After that change this
<v-select :options="lokasi_list" placeholder='Type location..'></v-select>
To this
<v-select label='nama_Location' :options="lokasi_list" placeholder='Type location..'></v-select>
After that, everything loads fine.
Vue's computed properties aren't normally used to populate vue data attributes, they normally take one or more data attributes and combine them into something different for the template to use.
In your code you've tried to populate the vue data attribute 'lokasi_list' in the computed property 'get_lokasi', but you never call 'get_lokasi' anywhere in the template so lokasi_list remains empty.
Another approach to this sort of situation is to use a vue method to fetch data from the php backend via an ajax call with something like axios, and you'd normally use that method in the vue app's created life cycle event to get the data asap.
e.g.
<script>
Vue.component('v-select', VueSelect.VueSelect);
var app = new Vue({
el: '#app',
data: {
lokasi_select: '',
lokasi_list: [],
},
created: function() {
this.fetchLocations();
},
methods: {
fetchLocations: function() {
axios.get('/api/locations-end-point')
.then((response) => {
this.lokasi_list = response.data //might need to change this to match how your php is returning the json
})
.catch((error) => {
//handle the error
})
}
}
});
</script>
Sorry to mention this, but in your php you've got:
if(isset($_GET['userid'])){
$condition = " id=".$_GET['userid'];
}
That looks like you were planning to use it as part of your sql, but it would have been vulnerable to SQL injection attacks, sorry If I'm pointing out something you already knew.

How can I add data to a Kotlin object and get it on a Vuejs page

I'm absolutely new to Kotlin. I'm trying to make a simple object on the backend side by Kotlin and get it on frontend Vuejs. How can I do something like this (this is the raw code of HeaderBar.kt, all my attempts were denied by compiler):
object HeaderBar {
val computed = object {
fun items(): Array<Item> {
items.add(Item(
"NY",
"Bill"
))
return items
}
}
data class Item(
val city: String,
val name: String
)
}
on Kotlin side?
And get the items on HeaderBar.vue. I'm not sure, but I do this by:
<template>
<div class="main-header">
<div v-for="item in items" class="items">
<span class="city">{{item.city}}</span>
<span class="name">{{item.name}}</span>
</div>
</div>
<template>
<script>
export default path.to.HeaderBar
</script>
First off all it's not simple question. Kotlin/Js not so mature as Kotlin/Jvm so there are many not so simple tasks.
First you need to somehow compile to javascript and then you need to attach Vue to kotlin/javascript code.
Webpack can make it easer, so I write a simple example to show you how to write your example in Kotlin.
!Warning!: all code below is just draft (and has been writen only in demonstration purpose), so use it in your projects with special caution!
Lets create project with below structure:
Application.kt:
package vue_test
fun VueJs(init: VueContext.() -> Unit) = Vue(VueContext().apply(init))
class VueContext {
var el: String = ""
var data: dynamic = js("{}")
}
fun main(args: Array<String>) {
val app: dynamic = VueJs {
el = "#app"
data = mapOf("items" to listOf(
Item("NY", "Bill"),
Item("Test", "Test2")
)).toJs()
}
}
data class Item(
val city: String,
val name: String
)
fun Map<String, Any>.toJs(): dynamic {
val result: dynamic = object {}
for ((key, value) in this) {
when (value) {
is String -> result[key] = value
is List<*> -> result[key] = (value as List<Any>).toJs()
else -> throw RuntimeException("value has invalid type")
}
}
return result
}
fun List<Any>.toJs(): dynamic {
val result: dynamic = js("[]")
for (value in this) {
when (value) {
is String -> result.push(value)
is Item -> {
result.push(value.toJs())
}
else -> throw RuntimeException("value has invalid type")
}
}
return result
}
fun Item.toJs(): dynamic {
val result: dynamic = object {}
result["city"] = this.city
result["name"] = this.name
return result
}
I have write few function toJs which converts Kotlin object to Js object. It theory you may use JSON serialization to simplify this, or other more simple solution (if exists).
Vue.kt
#file:JsModule("vue")
package vue_test
#JsName("default")
external open class Vue(init: dynamic)
In this file we have only Vue declarations.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Test project</title>
</head>
<body class="testApp">
<h1>Kotlin-Js test</h1>
<div id="app">
<div class="main-header">
<div v-for="item in items" class="items">
<span class="city">{{item.city}}</span>
<span class="name">{{item.name}}</span>
</div>
</div>
</div>
<script type="text/javascript" language="JavaScript" src="frontend.bundle.js"></script>
</body>
</html>
Buldle has been created by webpack, and I has put this script to bottom because Vue needed to start his manipulations only then all necessary html tags has been already exists.
My build.gradle file with kotlin-frontend plugin and kotlin-js plugin:
buildscript {
ext.kotlin_version = '1.2.10'
repositories {
mavenCentral()
jcenter()
maven {
url "https://dl.bintray.com/kotlin/kotlin-eap"
}
maven {
url "https://repo.gradle.org/gradle/libs-releases-local"
}
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.21"
}
}
group 'test'
version '1.0-SNAPSHOT'
apply plugin: 'kotlin-platform-js'
apply plugin: 'org.jetbrains.kotlin.frontend'
repositories {
mavenCentral()
}
kotlinFrontend {
sourceMaps = true
npm {
dependency("vue")
}
webpackBundle {
port = 8080
bundleName = "frontend"
contentPath = file('src/main/web')
webpackConfigFile = project.projectDir.path + '/webpack.config.js'
}
}
compileKotlin2Js {
kotlinOptions.metaInfo = true
kotlinOptions.outputFile = "$project.buildDir.path/js/${project.name}.js"
kotlinOptions.sourceMap = true
kotlinOptions.moduleKind = 'commonjs'
kotlinOptions.main = "call"
}
kotlin {
experimental {
coroutines 'enable'
}
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
settings.gradle
rootProject.name = 'test-kotlin-vue'
and last file, custom webpack configuration:
var config = require('./build/WebPackHelper.js')
var path = require('path')
module.exports = {
entry: config.moduleName,
output: {
path: path.resolve('./bundle'),
publicPath: '/build/',
filename: 'frontend.bundle.js'
},
module: {
rules: []
},
resolve: {
modules: [path.resolve('js'), path.resolve('..', 'src'), path.resolve('.'), path.resolve('node_modules')],
extensions: ['.js', '.css'],
alias: {
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
}
},
devtool: '#source-map'
};
console.log(module.exports.resolve.modules);
With kotlin-frontend plugin you could not use separate webpack config, but in this example Vue needed a full version to compile template, so it's needed to add alias in webpack. And I don't know how to do this in build.gradle.
Hope this will help you!
To start project with dev bundle run this command: gradle build webpack-run, and then open http://localhost:8080 in your browser
To stop test run command: gradle webpack-stop

Odoo 10 - Extend a Javascript of point of sale Module

i want to override a ReceiptScreen method from point_of_sale module.
var ReceiptScreenWidget = ScreenWidget.extend...
gui.define_screen({name:'receipt', widget: ReceiptScreenWidget});
In order to do this, i've created my own module but i don't know what steps follow to change the ReceiptScreenWidget.print() function.
Here is the screens.js that contains the Widget.Function that i want to override. (search for: ReceiptScreenWidget)
I tried to follow this example but the code is from Odoo 8 or 9 so i couldn't make it work.
*Odoo version: 10
JS
odoo.define('your_module_name.filename', function (require) {
"use strict";
var gui = require('point_of_sale.gui');
var screens = require('point_of_sale.screens');
var core = require('web.core');
var QWeb = core.qweb;
var _t = core._t;
screens.ReceiptScreenWidget.include({
print: function() {
// Your code
},
});
});
XML to add JS
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets" inherit_id="point_of_sale.assets">
<xpath expr="." position="inside">
<script type="text/javascript" src="/your_module_name/static/js/filename.js"></script>
</xpath>
</template>
</odoo>
Add that xml in __manifest__.py
{
...
...
'data': [
...
'views/above_xml_filename.xml',
],
....
}

Change text 'Add an item' in tree view odoo 9

How in custom module change text 'Add an item' to 'Add new row"?
Any simple solution?
Hello Pointer,
Using odoo 8
Try this below code,
your_module_name/view/custome_file_include.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="account assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<!-- Include External/Custom/Own JS File. And Order Maintain. -->
<script type="text/javascript" src="/your_module_name/static/src/js/custome_file_include.js"></script>
<script type="text/javascript" src="/your_module_name/static/src/js/custome_view_form.js"></script>
</xpath>
</template>
</data>
</openerp>
your_module_name/src/js/custome_file_include.js
openerp.fm_sale_order_ext_ept = function(instance) {
change_tree_view_add_item_name(instance);
}
your_module_name/src/js/custome_view_form.js
function change_tree_view_add_item_name(instance) {
instance.web.form.AddAnItemList.include({
pad_table_to: function (count) {
if (!this.view.is_action_enabled('create') || this.is_readonly()) {
this._super(count);
return;
}
this._super(count > 0 ? count - 1 : 0);
var self = this;
var columns = _(this.columns).filter(function (column) {
return column.invisible !== '1';
}).length;
if (this.options.selectable) { columns++; }
if (this.options.deletable) { columns++; }
var $cell = $('<td>', {
colspan: columns,
'class': this._add_row_class || ''
}).html(
$('<a>', {href: '#'}).text(_t("Add new row"))
.mousedown(function () {
// FIXME: needs to be an official API somehow
if (self.view.editor.is_editing()) {
self.view.__ignore_blur = true;
}
})
.click(function (e) {
e.preventDefault();
e.stopPropagation();
// FIXME: there should also be an API for that one
if (self.view.editor.form.__blur_timeout) {
clearTimeout(self.view.editor.form.__blur_timeout);
self.view.editor.form.__blur_timeout = false;
}
self.view.ensure_saved().done(function () {
self.view.do_add_record();
});
}));
var $padding = this.$current.find('tr:not([data-id]):first');
var $newrow = $('<tr>').append($cell);
if ($padding.length) {
$padding.replaceWith($newrow);
} else {
this.$current.replaceWith($newrow)
}
}
});
}
Using odoo9
First we create new module and given below is file structure of new module.
Module_Name
static
src
js
File_Name.js
views
File_Name.xml
__openerp__.py
Module_Name->views->File_Name.xml
Now we add the custome js in base odoo 9 module so we are create xml file and inherit base file and add our custome js,
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="account assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<!-- Include External/Custom/Own JS File. And Order Maintain. -->
<script type="text/javascript" src="/Module_Name/static/src/js/File_Name.js"></script>
</xpath>
</template>
</data>
</openerp>
Module_Name->static->src->js->File_Name.js
Now we are inherit base form_relation_widget.js js and modify this method,
odoo.define('Module_Name.File_Name', function (require) {
"use strict";
var core = require('web.core');
var ListView = require('web.ListView');
var _t = core._t;
var _lt = core._lt;
// Include "web.form_relational"
var form_relational = require('web.form_relational');
// Include X2ManyList Functionality and Modify X2ManyList Functionality
var form_relational = form_relational.X2ManyList.include({
pad_table_to: function (count) {
if (!this.view.is_action_enabled('create') || this.view.x2m.get('effective_readonly')) {
this._super(count);
return;
}
this._super(count > 0 ? count - 1 : 0);
var self = this;
var columns = _(this.columns).filter(function (column) {
return column.invisible !== '1';
}).length;
if (this.options.selectable) { columns++; }
if (this.options.deletable) { columns++; }
var $cell = $('<td>', {
colspan: columns,
'class': 'oe_form_field_x2many_list_row_add'
}).append(
$('<a>', {href: '#'}).text(_t("Add new row"))
.click(function (e) {
e.preventDefault();
e.stopPropagation();
// FIXME: there should also be an API for that one
if (self.view.editor.form.__blur_timeout) {
clearTimeout(self.view.editor.form.__blur_timeout);
self.view.editor.form.__blur_timeout = false;
}
self.view.save_edition().done(function () {
self.view.do_add_record();
});
}));
var $padding = this.$current.find('tr:not([data-id]):first');
var $newrow = $('<tr>').append($cell);
if ($padding.length) {
$padding.replaceWith($newrow);
} else {
this.$current.replaceWith($newrow);
}
},
});
});
Module_Name->openerp.py
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Module Name',
'version': '1.0',
'category': '',
'sequence': 1,
'summary': '',
'description': """ Give the Description of Module """,
'website': '',
'depends': ['web'],
'data': [
'views/File_Name.xml'
],
'demo': [],
'css': [],
'js' : [],
'installable': True,
'auto_install': False,
'application': True,
}
odoo_v9->web->static->src->js->views->form_relation_widget.js
Add X2ManyList : X2ManyList this line in base js (odoo9 module) form_relation_widget.js
return {
FieldMany2ManyTags: FieldMany2ManyTags,
AbstractManyField: AbstractManyField,
X2ManyList : X2ManyList, ////Add this line in this file
};
I hope my answer is helpful.
If any query so comment please.
An option could be that you enter on debug mode.
Then, go to Configuration -> Application Terms -> Synchronize Terms. In the dropdown Language, select English and wait until finish.
Go to Translated Terms, in the search field write "Add an item" and replace the text that is in Translation Value column.
It's worth say, this change will stored in the DB and all one2many relations will be affected.
This string is provided by JavaScript code. So you have to extend the js widget to change the name.

Aurelia Validation validation error detected, but no error message

I have a super simple code I'm trying to validate:
<template>
<form role="form" submit.delegate="submit()" validate.bind="validation">
<div class="form-group">
<label>Test Field</label>
<input type="text" value.bind="testField" class="form-control" validate="Description" placeholder="What needs to be done?" />
<button type="submit">Submit</button>
</div>
</form>
</template>
With the following viewmodel
define(["require", "exports", "../scripts/HttpClient", "aurelia-validation", "aurelia-framework"], function(require, exports, HttpClient) {
var AureliaValidation = require('aurelia-validation').Validation;
var MyViewModel = (function () {
function MyViewModel(httpClient, aureliaValidation, isReadyCallback) {
this.httpClient = httpClient;
var self = this;
self.setupValidation(aureliaValidation);
}
MyViewModel.prototype.activate = function (params, queryString, routeConfig) {
};
MyViewModel.prototype.setupValidation = function (validation) {
this.testField = "";
this.validation = validation.on(this).ensure('testField');
//validation
// .on(this.serviceMetadata.ServiceData[0])
// .ensure('Value');
this.validation = this.validation.notEmpty().maxLength(3);
};
MyViewModel.prototype.submit = function () {
debugger;
if (this.validation.checkAll()) {
//Do Something
}
return null;
};
MyViewModel.inject = [HttpClient, AureliaValidation];
return MyViewModel;
})();
return MyViewModel;
});
Now I got it working for the most part, and the validation is showing false on submit check, the textbox outline color changes etc., however it's not injecting the validation error messages into the DOM. There's no script error message either, how can I troubleshoot this?
Yes, I can see the validation messages in the validationProperties, but they're not written to the UI.
If your browser allows it, find the JSPM packages in the sources and put a breakpoint here, it's the point where the view strategy looks for labels to append error messages to. If you'd have this code in the open, I'd be happy to have a look for you.
Also, what version of aurelia/aurelia-validation are you using?
And finally, did you modify your sample before posting?
`<input value.bind="testField" validate="Description" />`
These two attributes are contradictory. It binds the value to testField, but then you use the validate attribute to explicitly show validation messages for property "Description".