Blog | LordVan's Page / Bloghttps://blog.lordvan.com/blog/2024-03-28T17:55:15.308505+00:00If you were looking for something specific you probably got redirected here from an old link to my (now gone) drupal blog. I migrated all the pages & blog entries to this blog, so just use the search here to find what you were looking for.Tryton templates caveat2023-10-10T12:58:56.780777+00:002024-03-28T17:36:17.729724+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-templates-caveat/<p>The way Tryton processes ODT templates causes it to sometimes do stuff that doesn'T make sense (like if you have a <code>FOR</code> loop before a page break and <code>/FOR</code> on apage itself after it should not keep the empty pages). A look into the content.xml file within the odt often then tells us why. In my case it was simply the formatting.</p>
<p>So I fixed this annoying issue by just marking it and clicking <code>"Remove direct formatting"</code> and now it gets rid of those without an issue.</p>
<p>Turns out the <code>text:p text:style-name="bla"</code> tags were causing it to consider it non-empty and keep it. Just something to keep in mind when designing templates. If weird stuff happens check the XML ;)</p>Tryton 6.0 -> 6.2 migration2021-12-23T22:37:16+00:002024-03-28T10:35:29.518028+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-60-62-migration/<p>Just some notes on the tryton migration from 6.0 to 6.2:</p>
<ul>
<li>SaleLine had a change so I needed to change my report template to use <code>line.unit.digits</code> instead of <code>line.unit_digits</code> not a big deal, but I was not aware .. probably somewhere in changelogs and I overlooked it.</li>
<li>Move line had a similar change from <code>move.unit_digits</code> to <code>move.uom.digits</code>.</li>
<li>The new custom report name feature is awesome. Just took me a minute to figure out what data is used for parsing that template. But basically if you want say <code><reportname>-<sale.number></code> then you'd just have to put <code>${ record.number }</code> or in my case <code>${ record.number.replace('/', '-') }</code> since I have slashes in the sale numbers. It automatically uses the report name and then after a hyphen appends whatever custom name you put. I'd have liked to not have the report name there automatically as suffix, but that is fine it is already a huge improvement to manually renaming it when saving it on the server.</li>
</ul>
<p>The rest worked fine so far, but we don't use that many modules (yet) so we will see if I encounter anything else</p>[Tryton] Adding a default account(ing) category to product (templates)2021-06-13T17:25:57.519843+00:002024-03-28T00:48:55.686920+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-adding-a-default-accounting-category-to-product-templates/<p>To optimize workflow (and avoid mistakes) I wanted to set a default account(ing) category so that tax,.. is set by default. Took a little bit of experimenting, but I got it:</p>
<pre>class Template(metaclass=PoolMeta):<br/> __name__ = 'product.template'<br/><br/> @classmethod<br/> def default_account_category(cls):<br/> try:<br/> return Pool().get('product.category').search([('name', '=', 'MWSt'), ('accounting', '=', True)])[0].id<br/> except:<br/> # FIXME: should I log an error here for not finding a hardcoded accounting category? <br/> return None<br/><br/></pre>
<p>I could have of course also returned the number for the tax rate I am usign as well, but I found this to be (a lot) more flexible should I ever want to make it user/admin configurable and not hardcode it. But for now this is more than fine.</p>[Tryton] product kit .. extra logic for components when expanded on sale quotation2021-06-13T09:53:10+00:002024-03-28T06:51:44.356750+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-product-kit-extra-logic-for-components-when-expanded-on-sale-quotation/<p>Since Tryton 6.0 had the awesome <a href="https://discuss.tryton.org/t/product-kit-support/1938" target="_blank">product kit</a> module added I saved a lot of time and only had to add some custom logic for my extra fields.</p>
<p>After some discussion on the IRC channel I had a vague idea of what to do (write my own get_components was up for discussion,..)</p>
<p>In the end I found a really simple way to do what I wanted after playing around in proteus a bit and inspecting the data. Basically I am making use of <prefix>line.component_children.</p>
<p>Since the components of a kit are expanded on quotation I just added one more method to my customized Sale class:</p>
<pre> @classmethod<br/> @ModelView.button<br/> @Workflow.transition('quotation')<br/> @set_employee('quoted_by')<br/> def quote(cls, sales):<br/> super(Sale, cls).quote(sales)<br/> # we need to apply folder_no to components of kits<br/> for sale in sales:<br/> for line in sale.lines:<br/> for lc in line.component_children:<br/> lc.folder_no = line.folder_no<br/> lc.save()<br/> cls.save(sales)</pre>
<p>I am not 100% sure if the last cls.save(sales) is needed, but I thought rather be safe than sorry. Now my components have the same folder_no as the kits which is needed for my project documentation.</p>Tryton upgrade from 5.8 to 6.02021-05-23T19:03:45+00:002024-03-28T10:27:07.855290+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-upgrade-vrom-58-to-60/<p>Upgrading Tryton from 5.8 to 6.0 was nearly completely painless - in part due to the fact I am only using a few modules so far (and my custom module is not too big either).</p>
<p>Following the <a href="https://discuss.tryton.org/t/migration-from-5-8-to-6-0/3603">Migration post</a> worked out just fine.</p>
<p>Here are the few things I had to change:</p>
<p>1) I was told beforehand on IRC by pokoli that the Report method get_context had an extra parameter <code>header</code> so I checked the source and added that (<a href="https://github.com/LordVan/tryton-modules/commit/3c7bf2d83c97644eee8053301695d5cfad42d6f4" target="_blank">commit on my github repo</a>).</p>
<p>2) The address field zip got renamed to the more generic postal_code (which is <a href="https://discuss.tryton.org/t/tryton-release-6-0/4094" target="_blank">mentioned here</a>) so I had to change the report.</p>
<p>(I also had to add correct DB URI escape syntax to my trytond config but that is not something everyone will have depending on the DB used, passwords,,..)</p>
<p>Now on to use the new product_kit module ... :)</p>
<p></p>Tryton, form state change with Eval not working with custom field (+ fix)2021-05-14T18:56:40.971095+00:002024-03-28T01:14:21.696846+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-form-state-change-with-eval-not-working-how-to-get-it-to-work/<p>I added a Boolean field to SaleLine - one that is not shown to the user but only set in the code as a flag. As the readonly state of just about all my custom fields should depend on that I added:</p>
<pre>states = {'readonly': ((Eval('sale_state') != 'draft') |
Eval('real_product')),
}, </pre>
<p>Frustratingly it did not work even though the rest of my code was executed in <code>on_change_product</code> as was seen on the assignment of values.</p>
<p>Took me a while to figure out what the problem was .. apparently for <code>Eval('real_product')</code> to work I needed to add this field to my <code>sale_line_form.xml</code>. So I did just that and to not show it to the user of course added <code>states = { 'invisible': True, }</code> to my Boolean field. Simple when you know it .. but takes a while to figure out if you don't.</p>Dolibarr -> Tryton data import finally done2021-04-25T19:01:31.777098+00:002024-03-28T12:13:13.733769+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/dolibarr-tryton-data-import-finally-done/<p>So I have finally imported all data from our old dolibarr install to tryton (the historical project data was missing - and because I needed to implement something in tryton first it had to wait a bit)</p>
<p>It's actually fairly simple. Due to the nature of the data (historical, not in-sequence with current projects,..) I had to use trytond-console instead of proteus but there are only a few differences for small imports like this (like pool.get(<model>) instead of Model.get (<model>) and of course it does not do all the checks proteus and the client do (which is good cuz otherwise it would be near impossible to import historical data this easily) ..</p>
<p>Anyway the code is on my <a href="https://github.com/LordVan/tryton-modules/tree/master/dolibarr_import" target="_blank">github</a>:</p>
<p></p>Small script to find duplicate contact_mechanisms for parties in tryton2021-01-06T14:02:46+00:002024-03-28T00:51:43.596566+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/small-script-to-find-duplicate-contact_mechanisms-for-parties-in-tryton/<p>Just a little script to find duplicate contact_mechanism entries on parties in tryton <a href="https://blog.lordvan.com/blog/ipython-loading-py-files-to-make-interactive-use-of-tryton-faster/">(how i run tryton stuff using ipython and proteus)</a>:</p>
<pre> for p in Party.find():
cms = p.contact_mechanisms
if cms:
nos = []
for cm in cms:
if f'{cm.type} {cm.value_compact}' in nos:
print(f'duplicate contact mechanism {p.code=} {p.name=} {cm.value} {cm.type}')
else:
nos.append(f'{cm.type} {cm.value_compact}')
</pre>
<p>I just ran this from ipython to find out if there are a lot of duplicates - turns out i had barely anything (and i fixed that before re-running the imports for good in the old system).</p>ipython loading .py files to make interactive use of tryton faster2021-01-04T09:40:34.526107+00:002024-03-27T10:34:03.583538+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/ipython-loading-py-files-to-make-interactive-use-of-tryton-faster/<p>So I was busy testing tryton import scripts .. which means constantly re-setting my DB to clear it (deleting just takes 10 times longer than SQL restore)..</p>
<p>But since I drop and recreate the DB the ipython session also needs to disconnect... which is a bit inconvenient because of setup,..</p>
<p>Fortunately ipython has <code>%load</code> - which makes this super easy:</p>
<p><img alt="Screenshot of script" height="519" src="https://blog.lordvan.com/static/media/uploads/Blog/Screenshots/shot-2021-01-04_10-24-27.jpg" width="978"/></p>
<p>(screenshot to show off just how nicely everything is even highlighted too)</p>
<p>now here the code to copy paste if someone wants it:</p>
<pre>import myinit
from proteus import config, Model, Wizard, Report
pcfg = config.set_trytond(database='tryton', config_file='/etc/tryton/trytond.conf')
Party = Model.get('party.party')
Addr = Model.get('party.address')
Cont = Model.get('party.contact_mechanism')
Note = Model.get('ir.note')
Lang = Model.get('ir.lang')
Categ = Model.get('party.category')
Country = Model.get('country.country')
SubD = Model.get('country.subdivision')
Cont = Model.get('party.contact_mechanism')
Ident = Model.get('party.identifier')
try:
prm, = Party.find([('code', '=', '1')])
except:
print('Could not load party with code 1')
</pre>
<p>myinit just contains the code to hide warnings from <a href="https://stackoverflow.com/questions/9031783/hide-all-warnings-in-ipython">this stackoverflow question</a></p>
<p>This is super useful in setting up the basic types I need for my testing.</p>Tryton Proteus adding Notes2021-01-03T15:45:57.272322+00:002024-03-28T06:45:02.649940+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-proteus-adding-notes/<p>So after a bit of experimenting I now know how to add Notes to other objects (like Party) for example:</p>
<p>(Assuming you got the connection set up in ipython using proteus or doign this in some script)</p>
<pre>Note = Model.get('ir.note')<br/>n2=Note()<br/>n2.message = 'this is a test note from proteus'<br/>n2.resource = prm # prm is a Party object that I fetched before<br/>n2.save()</pre>
<p>Fairly simple. not sure yet how to get notes that "belong" to a party object, but that is not important right now since I only need it for importing ;)</p>Quick'n dirty way to test my dolibarr -> tryton import scripts2020-12-31T14:00:09.022002+00:002024-03-28T06:43:01.787807+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/quickn-dirty-way-to-test-my-dolibarr-tryton-import-scripts/<p>Just a very quick one-liner I use when testing my import scripts on tryton (on gentoo):</p>
<pre>/etc/init.d/trytond stop; sudo -u postgres dropdb tryton; sudo -u postgres createdb -O tryton tryton; sudo -u postgres psql tryton < /var/lib/postgresql/tryton_minimal_2020-12-31.sql ; /etc/init.d/trytond start</pre>
<p>obviously the backup DB file needs to be created first ;)</p>GUI and trytond_import_countries/currencies gives trytond.model.modelstorage.SelectionValidationError2020-12-29T15:00:52.428405+00:002024-03-28T13:41:01.828409+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/gui-and-trytond_import_countriescurrencies-gives-trytondmodelmodelstorageselectionvalidationerror/<p>So I got this error when trying to run trytond_import_countries and trytond_import_currencies ..</p>
<pre> Update countries<br/> Traceback (most recent call last):<br/> File "/usr/lib/python-exec/python3.6/trytond_import_countries", line 11, in <module><br/> load_entry_point('trytond-country==5.8.0', 'console_scripts', 'trytond_import_countries')()<br/> File "/usr/lib64/python3.6/site-packages/trytond/modules/country/scripts/import_countries.py", line 171, in run<br/> main(args.database, args.config_file)<br/> File "/usr/lib64/python3.6/site-packages/trytond/modules/country/scripts/import_countries.py", line 151, in main<br/> do_import()<br/> File "/usr/lib64/python3.6/site-packages/trytond/modules/country/scripts/import_countries.py", line 156, in do_import<br/> countries = update_countries(countries)<br/> File "/usr/lib64/python3.6/site-packages/trytond/modules/country/scripts/import_countries.py", line 60, in update_countries<br/> Country.save(records)<br/> File "/usr/lib64/python3.6/site-packages/proteus/__init__.py", line 104, in newfunc<br/> return self.func(owner, *args, **kwargs)<br/> File "/usr/lib64/python3.6/site-packages/proteus/__init__.py", line 847, in save<br/> ids = proxy.create(values, context)<br/> File "/usr/lib64/python3.6/site-packages/proteus/config.py", line 188, in __call__<br/> result = rpc.result(meth(*args, **kwargs))<br/> File "/usr/lib64/python3.6/site-packages/trytond/modules/country/country.py", line 70, in create<br/> return super(Country, cls).create(vlist)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelsql.py", line 159, in wrapper<br/> return func(cls, *args, **kwargs)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelsql.py", line 659, in create<br/> list(translations.keys()), list(translations.values()))<br/> File "/usr/lib64/python3.6/site-packages/trytond/ir/translation.py", line 488, in set_ids<br/> cls.save(to_save)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/descriptors.py", line 33, in newfunc<br/> return self.func(owner, *args, **kwargs)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelstorage.py", line 1727, in save<br/> news = cls.create([save_values[r] for r in to_create])<br/> File "/usr/lib64/python3.6/site-packages/trytond/ir/translation.py", line 632, in create<br/> return super(Translation, cls).create(vlist)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelsql.py", line 159, in wrapper<br/> return func(cls, *args, **kwargs)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelsql.py", line 674, in create<br/> cls._validate(sub_records)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelstorage.py", line 76, in wrapper<br/> return func(*args, **kwargs)<br/> File "/usr/lib64/python3.6/site-packages/trytond/model/modelstorage.py", line 1306, in _validate<br/> **error_args))<br/> trytond.model.modelstorage.SelectionValidationError: Der Wert "de_AT" von Feld "Sprache" in "\xdcbersetzung" ist nicht in der Auswahl enthalte</pre>
<p>Turns out it was because the admin user had an invalid language set (de_AT is not something tryton knows by default .. changing to de or en in the settings of the client fixes the problem).</p>
<p>Alternatively add a language with the specified language code first :)</p>
<p>Thanks again cedk @ freenode IRC ;)</p>on getting party (company and people) data from dolibarr to import into tryton ..2019-02-01T17:06:54.151436+00:002024-03-28T15:45:30.589666+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/on-getting-party-company-and-people-data-from-dolibarr-to-import-into-tryton/<p>I tried with just exporting from postgresql like this:</p>
<pre>COPY (SELECT ROW_TO_JSON(t)<br/>FROM (SELECT * FROM llx_societe) t) to '/path/to/file/llx_societe_extrafields.json';</pre>
<p>but that gives me so much that I do not need and also still keeps the half-french colum names (which as someone who doesn't speak french is driving me mad and slowing me down..)</p>
<p>Warning: Postgresql does not seem to escape " from HTML so you need to escape it or remove it (which is hwat i did since I do not need it)</p>
<p>so I'll just make query and/or view to deal with this:</p>
<pre>SELECT s.rowid AS s_row,<br/> s.nom AS s_name,<br/> s.phone AS s_phone,<br/> s.fax AS s_fax,<br/> s.email AS s_email,<br/> s.url AS s_url,<br/> s.fax AS s_fax,<br/> s.address AS s_address,<br/> s.town AS s_town,<br/> s.zip AS s_zip,<br/> s.note_public AS s_note_public,<br/> s.note_private AS s_note_private,<br/> s.ape AS s_fbno,<br/> s.idprof4 AS s_dvrno,<br/> s.tva_assuj AS s_UST,<br/> s.tva_intra AS s_uid,<br/> s.code_client AS s_code_client,<br/> s.name_alias AS s_name_alias,<br/> s.siren AS s_siren,<br/> s.siret AS s_siret,<br/> s.client AS s_client,<br/> s_dep.nom AS s_county,<br/> s_reg.nom AS s_country,<br/> s.fk_forme_juridique,<br/> se.pn_name AS s_pn_name,<br/> sp.rowid AS sp_rowid,<br/> sp.lastname AS sp_lastname,<br/> sp.firstname AS sp_firstname,<br/> sp.address as sp_address,<br/> sp.civility AS sp_civility,<br/> sp.address AS sp_address,<br/> sp.zip AS sp_zip,<br/> sp.town AS sp_town,<br/> sp_dep.nom AS sp_county,<br/> sp_reg.nom AS sp_country,<br/> sp.fk_pays AS sp_fk_pays,<br/> sp.birthday AS sp_birthday,<br/> sp.poste AS sp_poste,<br/> sp.phone AS sp_phone,<br/> sp.phone_perso AS sp_phone_perso,<br/> sp.phone_mobile AS sp_phone_mobile,<br/> sp.fax AS sp_fax,<br/> sp.email AS sp_email,<br/> sp.priv AS sp_priv,<br/> sp.note_private AS sp_note_private,<br/> sp.note_public AS sp_note_public<br/> <br/><br/>FROM llx_societe AS s<br/>INNER JOIN llx_societe_extrafields AS se ON se.fk_object = s.rowid<br/>LEFT JOIN llx_socpeople AS sp ON sp.fk_soc = s.rowid<br/>LEFT JOIN llx_c_departements AS s_dep ON s.fk_departement = s_dep.rowid<br/>LEFT JOIN llx_c_regions AS s_reg ON s_dep.fk_region = s_reg.rowid<br/>LEFT JOIN llx_c_departements AS sp_dep ON sp.fk_departement = sp_dep.rowid<br/>LEFT JOIN llx_c_regions AS sp_reg ON sp_dep.fk_region = sp_reg.rowid<br/>ORDER BY s_name, sp_lastname, sp_firstname;</pre>
<p></p>Using proteus to browse / edit / .. tryton's data2019-01-05T15:28:29+00:002024-03-28T15:03:47.058062+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/using-proteus-to-browse-edit-trytons-data/<p>Going to be using this blog post to add bits and pieces of how to use proteus to handle data in tryton.</p>
<p>Just noticed the proteus readme is quite good: here's a link to the <a href="https://github.com/tryton/proteus">proteus github</a></p>
<p><strong>IMPORTANT</strong>: One thing I noticed (the hard way) is that if you are connected with a proteus session and you add&activate a module (at least when it is not done using proteus) you need to re-connect as it does not seem to add things like extra fields added to models otherwise.</p>
<p>First thing: connect:</p>
<pre>from proteus import config, Model, Wizard, Report<br/>pcfg = config.set_trytond(database='trytond', config_file='/etc/tryton/trytond.conf')</pre>
<p>Then we just get ourselved our parties:</p>
<pre>Party = Model.get('party.party')
all_parties=Party.find()
for p in all_parties:
print(p.name)
print(p.addresses[0].full_address
)</pre>
<p>This will print out all names and the first full address of each.</p>
<p>Party Relations (a seperate module):</p>
<pre>p.relations</pre>
<p>Would give you output similar to this (if there are relations - in my case 2):</p>
<pre>[proteus.Model.get('party.relation.all')(2),<br/> proteus.Model.get('party.relation.all')(4)]</pre>
<p>Interesting fields there (for me):</p>
<pre>p.relations[0].type.name # returns the name of the relation as entered<br/>p.relations[0].reverse # reverse relation as entered<br/># the next 2 are self explainatory anyway just note the '_' with from <br/>p.relations[0].to <br/>p.relations[0].from_</pre>
<p>Now to add a new one:</p>
<pre>np = Party()<br/>np.name='Test Customer from Proteus'<br/>np.save()</pre>
<p>This just creates a new party with just a name. default values that are set up (like default language) are set. Until it is saved the <code>id</code> (<code>np.id</code>) is -1. By default it also comes with one (empty address).</p>
<p>Here's how to edit/add:</p>
<pre>np.addresses[0].zip='1234'<br/>np.addresses.new(zip='2345')<br/>np.save() # don't forget this</pre>
<p>Extra fields from other (possibly own) can be accessed exactly the same way as the normal ones (just don't forget to reconnect - like i did ;) )</p>
<p>Here's how you refresh the data:</p>
<pre>np.reload()</pre>
<p>d</p>
<p></p>tryton -- ipython, proteus2018-10-14T09:22:51.407965+00:002024-03-26T12:50:20.487986+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-ipython-proteus/<pre>So after being told on IRC that you can use (i)python and proteus to poke around a running tryton instance(thanks for that hint btw) I tried it and had some "fun" right away:</pre>
<pre>from proteus import config,Model
pcfg = config.set_trytond(database='trytond', config_file='/etc/tryon/trytond.conf')</pre>
<p>gave me this:</p>
<pre>---------------------------------------------------------------------------<br/>ValueError Traceback (most recent call last)<br/>/usr/lib64/python3.5/site-packages/trytond/backend/__init__.py in get(prop)<br/> 31 ep, = pkg_resources.iter_entry_points(<br/>---> 32 'trytond.backend', db_type)<br/> 33 except ValueError:<br/><br/>ValueError: not enough values to unpack (expected 1, got 0)<br/><br/>During handling of the above exception, another exception occurred:<br/><br/>ImportError Traceback (most recent call last)<br/><ipython-input-2-300353cf02f5> in <module>()<br/>----> 1 pcfg = config.set_trytond(database='trytond', config_file='/etc/tryon/trytond.conf')<br/><br/>/usr/lib64/python3.5/site-packages/proteus/config.py in set_trytond(database, user, config_file)<br/> 281 config_file=None):<br/> 282 'Set trytond package as backend'<br/>--> 283 _CONFIG.current = TrytondConfig(database, user, config_file=config_file)<br/> 284 return _CONFIG.current<br/> 285<br/><br/>/usr/lib64/python3.5/site-packages/proteus/config.py in __init__(self, database, user, config_file)<br/> 232 self.config_file = config_file<br/> 233<br/>--> 234 Pool.start()<br/> 235 self.pool = Pool(database_name)<br/> 236 self.pool.init()<br/><br/>/usr/lib64/python3.5/site-packages/trytond/pool.py in start(cls)<br/> 100 for classes in Pool.classes.values():<br/> 101 classes.clear()<br/>--> 102 register_classes()<br/> 103 cls._started = True<br/> 104<br/><br/>/usr/lib64/python3.5/site-packages/trytond/modules/__init__.py in register_classes()<br/> 339 Import modules to register the classes in the Pool<br/> 340 '''<br/>--> 341 import trytond.ir<br/> 342 trytond.ir.register()<br/> 343 import trytond.res<br/><br/>/usr/lib64/python3.5/site-packages/trytond/ir/__init__.py in <module>()<br/> 2 # this repository contains the full copyright notices and license terms.<br/> 3 from ..pool import Pool<br/>----> 4 from .configuration import *<br/> 5 from .translation import *<br/> 6 from .sequence import *<br/><br/>/usr/lib64/python3.5/site-packages/trytond/ir/configuration.py in <module>()<br/> 1 # This file is part of Tryton. The COPYRIGHT file at the top level of<br/> 2 # this repository contains the full copyright notices and license terms.<br/>----> 3 from ..model import ModelSQL, ModelSingleton, fields<br/> 4 from ..cache import Cache<br/> 5 from ..config import config<br/><br/>/usr/lib64/python3.5/site-packages/trytond/model/__init__.py in <module>()<br/> 1 # This file is part of Tryton. The COPYRIGHT file at the top level of<br/> 2 # this repository contains the full copyright notices and license terms.<br/>----> 3 from .model import Model<br/> 4 from .modelview import ModelView<br/> 5 from .modelstorage import ModelStorage, EvalEnvironment<br/><br/>/usr/lib64/python3.5/site-packages/trytond/model/model.py in <module>()<br/> 6 from functools import total_ordering<br/> 7<br/>----> 8 from trytond.model import fields<br/> 9 from trytond.error import WarningErrorMixin<br/> 10 from trytond.pool import Pool, PoolBase<br/><br/>/usr/lib64/python3.5/site-packages/trytond/model/fields/__init__.py in <module>()<br/> 2 # this repository contains the full copyright notices and license terms.<br/> 3<br/>----> 4 from .field import *<br/> 5 from .boolean import *<br/> 6 from .integer import *<br/><br/>/usr/lib64/python3.5/site-packages/trytond/model/fields/field.py in <module>()<br/> 18 from ...rpc import RPC<br/> 19<br/>---> 20 Database = backend.get('Database')<br/> 21<br/> 22<br/><br/>/usr/lib64/python3.5/site-packages/trytond/backend/__init__.py in get(prop)<br/> 32 'trytond.backend', db_type)<br/> 33 except ValueError:<br/>---> 34 raise exception<br/> 35 mod_path = os.path.join(ep.dist.location,<br/> 36 *ep.module_name.split('.')[:-1])<br/><br/>/usr/lib64/python3.5/site-packages/trytond/backend/__init__.py in get(prop)<br/> 24 if modname not in sys.modules:<br/> 25 try:<br/>---> 26 __import__(modname)<br/> 27 except ImportError as exception:<br/> 28 if not pkg_resources:<br/><br/>ImportError: No module named 'trytond.backend.'</pre>
<p>Took me a while to figure out I just had a typon in the config file path. Since that cost me some time I thought I'd put it on here so that maybe someone else who makes the same mistake doesn't waste as much time on it as me ;) -- and thanks to the always helpful people on IRC #tryton@freenode</p>Tryton Module Development2018-09-28T12:03:02+00:002024-03-26T10:13:24.359948+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-module-development/<p>So I've finally got around to really start Tryton module dev to customize it to what we need.</p>
<p>I plan to put stuff that is useful as examples or maybe directly as-is on my github: <a>https://github.com/LordVan/tryton-modules</a></p>
<p>On a side note this is trytond-4.8.4 running on python 3.5 at the moment.</p>
<p>The first module just (re-)adds the description filed to the sale lines in the sale module (entry). This by itself is vaguely useful for me but mostly was to figure out how this works. I have to say once figured out it is really easy - the hardest part was to get the XML right for someone who is not familiar with the structure. I'd like to thank the people who helped me on IRC ( #tryton@freenode )</p>
<p>The next step will be to add some custom fields to this and products.</p>
<p>To add this module you can follow the steps in the documentation: <a href="https://tryton-documentation.readthedocs.io/en/latest/developer_guide/example_library_1.html">Tryton by example</a></p>
<p></p>tryton with postgresql on another server & permissions2018-07-14T13:28:18.767027+00:002024-03-28T17:55:15.308505+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-with-postgresql-on-another-server-permissions/<p>A little follow-up to my post about setting up tryton on Gentoo:</p>
<p>If you run postgresql on a different server you need to deal with setting up the permissions on the postgresql side.</p>
<p>What I was not aware of at that time is that trytond (not trytond-admin it seems) requires access to the template1 database too.</p>
<p>For some reason Trytond did silently fail to start. The only log messages I did see were of level INFO about connecting to template1:</p>
<pre>Sat Jul 14 13:17:44 2018] INFO:trytond.backend.postgresql.database:connect to "template1"<br/>Sat Jul 14 13:17:44 2018] INFO:werkzeug:192.168.0.151 - - [14/Jul/2018 13:17:44] "POST / HTTP/1.1" 200 -<br/>Sat Jul 14 13:17:44 2018] INFO:werkzeug:192.168.0.151 - - [14/Jul/2018 13:17:44] "POST / HTTP/1.1" 200 -</pre>
<p>so you need to set that up in your pg_hba.conf too. To give an example:</p>
<pre># TYPE DATABASE USER ADDRESS METHOD<br/>host trytond trytond 192.168.0.X/0 scram-sha-256<br/>host template1 trytond 192.168.0.X/0 scram-sha-256</pre>
<p>As you can see I give the trytond user access to the trytond database (and in the next line to template1 too). For some reason trytond-admin does not require this, but it would be nice if trytond did log about not getting access to "template".</p>
<p>Of course it needs to be set up to accept connections on the tcp/ip port you set up in postgresql.conf.</p>Tryton setup & config2018-03-01T08:10:05+00:002024-03-28T10:20:34.775588+00:00lordvanhttps://blog.lordvan.com/blog/author/lordvan/https://blog.lordvan.com/blog/tryton-setup-config/<p>Because I keep forgetting stuff I need to do (or the order) here a very quick overview:</p>
<p>Install trytond, modules + deps (on gentoo add the tryton overlay and just emerge)</p>
<p>If you don'T use sqlite create a user (and database) for tryton.</p>
<p>Gentoo Init scripts use /etc/conf.d/trytond (here's mine):</p>
<pre># Location of the configuration file<br/>CONFIG=/etc/tryton/trytond.conf<br/># Location of the logging configuration file<br/>LOGCONF=/etc/tryton/logging.conf<br/># The database names to load (space separated)<br/>DATABASES=tryton</pre>
<p>since it took me a while to find a working logging.conf example here's my working one:</p>
<pre>[formatters]<br/>keys=simple<br/><br/>[handlers]<br/>keys=rotate,console<br/><br/>[loggers]<br/>keys=root<br/><br/>[formatter_simple]<br/>format=%(asctime)s] %(levelname)s:%(name)s:%(message)s<br/>datefmt=%a %b %d %H:%M:%S %Y<br/><br/>[handler_rotate]<br/>class=handlers.TimedRotatingFileHandler<br/>args=('/var/log/trytond/trytond.log', 'D', 1, 120)<br/>formatter=simple<br/><br/>[handler_console]<br/>class=StreamHandler<br/>formatter=simple<br/>args=(sys.stdout,)<br/><br/>[logger_root]<br/>level=INFO<br/>handlers=rotate,console</pre>
<p>(Not going into details here, if you want to know more there are plenty of resources online)</p>
<p>As for config I went and got an example online (from open Suse) and modified it:</p>
<pre># /etc/tryton/trytond.conf - Configuration file for Tryton Server (trytond)<br/>#<br/># This file contains the most common settings for trytond (Defaults<br/># are commented).<br/># For more information read<br/># /usr/share/doc/trytond-<version>/<br/><br/>[database]<br/># Database related settings<br/><br/># The URI to connect to the SQL database (following RFC-3986)<br/># uri = database://username:password@host:port/<br/># (Internal default: sqlite:// (i.e. a local SQLite database))<br/>#<br/># PostgreSQL via Unix domain sockets<br/># (e.g. PostgreSQL database running on the same machine (localhost))<br/>#uri = postgresql://tryton:tryton@/<br/>#<br/>#Default setting for a local postgres database<br/>#uri = postgresql:///<br/><br/>#<br/># PostgreSQL via TCP/IP<br/># (e.g. connecting to a PostgreSQL database running on a remote machine or<br/># by means of md5 authentication. Needs PostgreSQL to be configured to accept<br/># those connections (pg_hba.conf).)<br/>#uri = postgresql://tryton:tryton@localhost:5432/<br/>uri = postgresql://tryton:mypassword@localhost:5432/<br/><br/># The path to the directory where the Tryton Server stores files.<br/># The server must have write permissions to this directory.<br/># (Internal default: /var/lib/trytond)<br/>path = /var/lib/tryton<br/><br/># Shall available databases be listed in the client?<br/>#list = True<br/><br/># The number of retries of the Tryton Server when there are errors<br/># in a request to the database<br/>#retry = 5<br/><br/># The primary language, that is used to store entries in translatable<br/># fields into the database.<br/>#language = en_US<br/>language = de_AT<br/><br/>[ssl]<br/># SSL settings<br/># Activation of SSL for all available protocols.<br/># Uncomment the following settings for key and certificate<br/># to enable SSL.<br/><br/># The path to the private key<br/>#privatekey = /etc/ssl/private/ssl-cert-snakeoil.key<br/><br/># The path to the certificate<br/>#certificate = /etc/ssl/certs/ssl-cert-snakeoil.pem<br/><br/>[jsonrpc]<br/># Settings for the JSON-RPC network interface<br/><br/># The IP/host and port number of the interface<br/># (Internal default: localhost:8000)<br/>#<br/># Listen on all interfaces (IPv4)<br/><br/>listen = 0.0.0.0:8000<br/><br/>#<br/># Listen on all interfaces (IPv4 and IPv6)<br/>#listen = [::]:8000<br/><br/># The hostname for this interface<br/>#hostname =<br/><br/># The root path to retrieve data for GET requests<br/>#data = jsondata<br/><br/>[xmlrpc]<br/># Settings for the XML-RPC network interface<br/><br/># The IP/host and port number of the interface<br/>#listen = localhost:8069<br/><br/>[webdav]<br/># Settings for the WebDAV network interface<br/><br/># The IP/host and port number of the interface<br/>#listen = localhost:8080<br/>listen = 0.0.0.0:8080<br/><br/>[session]<br/># Session settings<br/><br/># The time (in seconds) until an inactive session expires<br/>timeout = 3600<br/><br/># The server administration password used by the client for<br/># the execution of database management tasks. It is encrypted<br/># using using the Unix crypt(3) routine. A password can be<br/># generated using the following command line (on one line):<br/># $ python -c 'import getpass,crypt,random,string; \<br/># print crypt.crypt(getpass.getpass(), \<br/># "".join(random.sample(string.ascii_letters + string.digits, 8)))'<br/># Example password with 'admin'<br/>#super_pwd = jkUbZGvFNeugk<br/>super_pwd = <your pwd><br/><br/><br/>[email]<br/># Mail settings<br/><br/># The URI to connect to the SMTP server.<br/># Available protocols are:<br/># - smtp: simple SMTP<br/># - smtp+tls: SMTP with STARTTLS<br/># - smtps: SMTP with SSL<br/>#uri = smtp://localhost:25<br/>uri = smtp://localhost:25<br/><br/># The From address used by the Tryton Server to send emails.<br/>from = <a href="mailto:tryton@%3Cyour-domain.tld%3E">tryton@<your-domain.tld></a><br/><br/>[report]<br/># Report settings<br/><br/># Unoconv parameters for connection to the unoconv service.<br/>#unoconv = pipe,name=trytond;urp;StarOffice.ComponentContext<br/><br/># Module settings<br/>#<br/># Some modules are reading configuration parameters from this<br/># configuration file. These settings only apply when those modules<br/># are installed.<br/>#<br/>#[ldap_authentication]<br/># The URI to connect to the LDAP server.<br/>#uri = ldap://host:port/dn?attributes?scope?filter?extensions<br/># A basic default URL could look like<br/>#uri = ldap://localhost:389/<br/><br/>[web]<br/># Path for the web-frontend<br/>#root = /usr/lib/node-modules/tryton-sao<br/>listen = 0.0.0.0:8000<br/>root = /usr/share/sao<br/><br/></pre>
<p>Set up the database tables, modules, superuser</p>
<pre>trytond-admin -c /etc/tryton/trytond.conf -d tryton --all</pre>
<p>Should you forget to set your superuser password (or need to change it later):</p>
<pre>trytond-admin -c /etc/tryton/trytond.conf -d tryton -p</pre>
<p>It's now time to connect a client to it and enable & configure the modules (make sure to finish the basic configuration (including accounts,..) otherwise you have to either restart, or know what exactly needs to be set up accounting wise !</p>
<ul>
<li>configure user(s)</li>
<li>enable account_eu (config and setup take a while)</li>
<li>set up company
<ul>
<li>create a party for it</li>
<li>assign currency and timezone</li>
</ul>
</li>
<li>set up chart of accounts from the template (only do this manually if you really know what you - and tryton - needs !!)
<ul>
<li>choose company & pick the template (e.g. "Minimaler Kontenplan" (if using german) )
<ul>
<li>set the defaults (only one per option usually)</li>
</ul>
</li>
</ul>
</li>
<li>after applying the above activate and configure whatever else you need (sale, timesheet, ...)</li>
</ul>
<p>during this you can watch trytond.log to see what happens behind the scenes (e.g. country module takes a while,..)</p>
<p>How to add languages:</p>
<ul>
<li>Administration -> Localization -> Languages -> add the language and set it to <br/>active and translatable </li>
</ul>
<p>If you install new modules or languages run trytond-admin ... --all again (see above) </p>
<p>UPDATE (2020-12):</p>
<p>Country and currency data is no longer imported automatically (since version ..)</p>
<p>you now have to run this:</p>
<pre><a href="https://github.com/tryton/country">https://github.com/tryton/country</a></pre>
<p>Because I keep forgetting stuff I need to do (or the order) here a very quick overview:</p>
<p>Install trytond, modules + deps (on gentoo add the tryton overlay and just emerge)</p>
<p>If you don'T use sqlite create a user (and database) for tryton.</p>
<p>Gentoo Init scripts use /etc/conf.d/trytond (here's mine):</p>
<pre># Location of the configuration file<br/>CONFIG=/etc/tryton/trytond.conf<br/># Location of the logging configuration file<br/>LOGCONF=/etc/tryton/logging.conf<br/># The database names to load (space separated)<br/>DATABASES=tryton</pre>
<p>since it took me a while to find a working logging.conf example here's my working one:</p>
<pre>[formatters]<br/>keys=simple<br/><br/>[handlers]<br/>keys=rotate,console<br/><br/>[loggers]<br/>keys=root<br/><br/>[formatter_simple]<br/>format=%(asctime)s] %(levelname)s:%(name)s:%(message)s<br/>datefmt=%a %b %d %H:%M:%S %Y<br/><br/>[handler_rotate]<br/>class=handlers.TimedRotatingFileHandler<br/>args=('/var/log/trytond/trytond.log', 'D', 1, 120)<br/>formatter=simple<br/><br/>[handler_console]<br/>class=StreamHandler<br/>formatter=simple<br/>args=(sys.stdout,)<br/><br/>[logger_root]<br/>level=INFO<br/>handlers=rotate,console</pre>
<p>(Not going into details here, if you want to know more there are plenty of resources online)</p>
<p>As for config I went and got an example online (from open Suse) and modified it:</p>
<pre># /etc/tryton/trytond.conf - Configuration file for Tryton Server (trytond)<br/>#<br/># This file contains the most common settings for trytond (Defaults<br/># are commented).<br/># For more information read<br/># /usr/share/doc/trytond-<version>/<br/><br/>[database]<br/># Database related settings<br/><br/># The URI to connect to the SQL database (following RFC-3986)<br/># uri = database://username:password@host:port/<br/># (Internal default: sqlite:// (i.e. a local SQLite database))<br/>#<br/># PostgreSQL via Unix domain sockets<br/># (e.g. PostgreSQL database running on the same machine (localhost))<br/>#uri = postgresql://tryton:tryton@/<br/>#<br/>#Default setting for a local postgres database<br/>#uri = postgresql:///<br/><br/>#<br/># PostgreSQL via TCP/IP<br/># (e.g. connecting to a PostgreSQL database running on a remote machine or<br/># by means of md5 authentication. Needs PostgreSQL to be configured to accept<br/># those connections (pg_hba.conf).)<br/>#uri = postgresql://tryton:tryton@localhost:5432/<br/>uri = postgresql://tryton:mypassword@localhost:5432/<br/><br/># The path to the directory where the Tryton Server stores files.<br/># The server must have write permissions to this directory.<br/># (Internal default: /var/lib/trytond)<br/>path = /var/lib/tryton<br/><br/># Shall available databases be listed in the client?<br/>#list = True<br/><br/># The number of retries of the Tryton Server when there are errors<br/># in a request to the database<br/>#retry = 5<br/><br/># The primary language, that is used to store entries in translatable<br/># fields into the database.<br/>#language = en_US<br/>language = de_AT<br/><br/>[ssl]<br/># SSL settings<br/># Activation of SSL for all available protocols.<br/># Uncomment the following settings for key and certificate<br/># to enable SSL.<br/><br/># The path to the private key<br/>#privatekey = /etc/ssl/private/ssl-cert-snakeoil.key<br/><br/># The path to the certificate<br/>#certificate = /etc/ssl/certs/ssl-cert-snakeoil.pem<br/><br/>[jsonrpc]<br/># Settings for the JSON-RPC network interface<br/><br/># The IP/host and port number of the interface<br/># (Internal default: localhost:8000)<br/>#<br/># Listen on all interfaces (IPv4)<br/><br/>listen = 0.0.0.0:8000<br/><br/>#<br/># Listen on all interfaces (IPv4 and IPv6)<br/>#listen = [::]:8000<br/><br/># The hostname for this interface<br/>#hostname =<br/><br/># The root path to retrieve data for GET requests<br/>#data = jsondata<br/><br/>[xmlrpc]<br/># Settings for the XML-RPC network interface<br/><br/># The IP/host and port number of the interface<br/>#listen = localhost:8069<br/><br/>[webdav]<br/># Settings for the WebDAV network interface<br/><br/># The IP/host and port number of the interface<br/>#listen = localhost:8080<br/>listen = 0.0.0.0:8080<br/><br/>[session]<br/># Session settings<br/><br/># The time (in seconds) until an inactive session expires<br/>timeout = 3600<br/><br/># The server administration password used by the client for<br/># the execution of database management tasks. It is encrypted<br/># using using the Unix crypt(3) routine. A password can be<br/># generated using the following command line (on one line):<br/># $ python -c 'import getpass,crypt,random,string; \<br/># print crypt.crypt(getpass.getpass(), \<br/># "".join(random.sample(string.ascii_letters + string.digits, 8)))'<br/># Example password with 'admin'<br/>#super_pwd = jkUbZGvFNeugk<br/>super_pwd = <your pwd><br/><br/><br/>[email]<br/># Mail settings<br/><br/># The URI to connect to the SMTP server.<br/># Available protocols are:<br/># - smtp: simple SMTP<br/># - smtp+tls: SMTP with STARTTLS<br/># - smtps: SMTP with SSL<br/>#uri = smtp://localhost:25<br/>uri = smtp://localhost:25<br/><br/># The From address used by the Tryton Server to send emails.<br/>from = <a href="mailto:tryton@%3Cyour-domain.tld%3E">tryton@<your-domain.tld></a><br/><br/>[report]<br/># Report settings<br/><br/># Unoconv parameters for connection to the unoconv service.<br/>#unoconv = pipe,name=trytond;urp;StarOffice.ComponentContext<br/><br/># Module settings<br/>#<br/># Some modules are reading configuration parameters from this<br/># configuration file. These settings only apply when those modules<br/># are installed.<br/>#<br/>#[ldap_authentication]<br/># The URI to connect to the LDAP server.<br/>#uri = ldap://host:port/dn?attributes?scope?filter?extensions<br/># A basic default URL could look like<br/>#uri = ldap://localhost:389/<br/><br/>[web]<br/># Path for the web-frontend<br/>#root = /usr/lib/node-modules/tryton-sao<br/>listen = 0.0.0.0:8000<br/>root = /usr/share/sao<br/><br/></pre>
<p>Set up the database tables, modules, superuser</p>
<pre>trytond-admin -c /etc/tryton/trytond.conf -d tryton --all</pre>
<p>Should you forget to set your superuser password (or need to change it later):</p>
<pre>trytond-admin -c /etc/tryton/trytond.conf -d tryton -p</pre>
<p>It's now time to connect a client to it and enable & configure the modules (make sure to finish the basic configuration (including accounts,..) otherwise you have to either restart, or know what exactly needs to be set up accounting wise !</p>
<ul>
<li>configure user(s)</li>
<li>enable account_eu (config and setup take a while)</li>
<li>set up company
<ul>
<li>create a party for it</li>
<li>assign currency and timezone</li>
</ul>
</li>
<li>set up chart of accounts from the template (only do this manually if you really know what you - and tryton - needs !!)
<ul>
<li>choose company & pick the template (e.g. "Minimaler Kontenplan" (if using german) )
<ul>
<li>set the defaults (only one per option usually)</li>
</ul>
</li>
</ul>
</li>
<li>after applying the above activate and configure whatever else you need (sale, timesheet, ...)</li>
</ul>
<p>during this you can watch trytond.log to see what happens behind the scenes (e.g. country module takes a while,..)</p>
<p>How to add languages:</p>
<ul>
<li>Administration -> Localization -> Languages -> add the language and set it to <br/>active and translatable </li>
</ul>
<p>If you install new modules or languages run trytond-admin ... --all again (see above) </p>
<p>UPDATE (2020-12):</p>
<p>Country and <a href="https://docs.tryton.org/projects/modules-currency/en/latest/setup.html#loading-and-updating-currencies">currency</a> data is no longer imported automatically (Version 5.4)</p>
<p>you now have to run these 2 commands for that:</p>
<pre>trytond_import_currencies -c /etc/tryton/trytond.conf -d tryton<br/>trytond_import_countries -c /etc/tryton/trytond.conf -d tryton</pre>
<p>On a side note.. this cannot be done before those 2 modules are activated. So i recommend connecting with the client, activating those 2 modules, then running the scripts and after that adding company,..</p>
<p></p>
<p></p>