06 Desember 2014

Tentang Masalah Datetime - UTC OpenERP 7 & 8

Bismillahirrahmaanirrahiim

Hmm sulit sekali lepas dari kata OpenERP.. harusnya Odoo yaa hehe ..
iya ini tentang konsep datetime di OE 7 dan 8. hmm sebenarnya juga OE 6.1

Memang konsep ini dimulai sejak OE 6.1
Sedangkan di OE 6.0 masih "normal"

Maksudnya gimana nih?
Dulu di OE 6.0 kalau kita input datetime 06/12/2014 07:30:58
maka saat disimpan di database juga disimpan sebagai  06/12/2014 07:30:58

Sedangkan, mulai di OE 6.1 dst, maka akan disimpan di Postgre sebagai datetime yang dikembalikan ke basic UTC yaitu UTC+0 sesuai timezone masing-masing user

Di masing-masing user, ada preferences  untuk setting local timezone. Contoh saya set timezone Asia/Jakarta (UTC+7). Nah maka ketika saya input 06/12/2014 07:30:58 maka akan disimpan sebagai 06/12/2014 00:30:58
Sedangkan jika ada user lain di UTC-2 misalkan, dengan input yang sama maka akan disimpan sebagai 06/12/2014 09:30:58

Nope, ini BUKAN BUGS. Ini memang disain yang dibuat demikian.

Nah terus apa masalahnya?
toh nanti pas tampil tetap sesuai timezone yang dipilih tiap user?
betul... di web tentu akan tampil sesuai timezone kita... gak perduli dengan timezone yg kita set di laptop. semua hanya dipengaruhi timezone yg diset di masing-masing user. cmiiw

Masalahnya adalah ketika berhubungan dengan report.
Kalau kita buat report pakai RML standard, sudah ada solusinya, yaitu
pakai [[ formatLang(fielddatetime, datetime=True) ]]

Nah kalau pakai query misalnya, atau pakai browse biasa... maksudnya buat function di *.py untuk menghasilkan datetime sesuai timezone, nah itu yang jadi masalah...

Jadi ceritanya beberapa minggu lalu, saya dapat task untuk export data ke dalam xls. Saat itu saya menggunakan python-xlwt (HINT: xlsxwriter ternyata lebih powerful lho. Saya gak pake aeroo ya.. krn pada kenyataannya dengan langsung generate dengan xlwt/xlxwriter akan jauuuuuuuuuuuuh lebih cepat saat generate data banyak..

Lalu saya gunakan browse biasa kemudian read field datetime, maka akan keluar datetime dengan basic UTC. Dan si user yang request modul ini jadi protes, karena gak sesuai dengan timezone mereka...

yaudah pakai formatLang aja?
sayangnya hanya bisa dipakai di rml saja.. cmiiw

terus gimana?

Alhamdulillah, setelah ngubek2 src code dan gugling sana sini, dapatlah solusi ini...

jangan lupa import pytz nya ya...

Nah selanjutnya tinggal disesuaikan deh mau ambil timezone dari mana.
kalau di code tsb, diambil dari timezone user yg login.

kalau misalnya untuk lembur, mungkin disesuaikan dengan timezone masing2 karyawan. karena bisa jadi karyawan nya tersebar di penjuru dunia dengan berbagai variasi timezone.

Demikian
semoga bermanfaat
kalau ada yang salah mohon bantu koreksi yaa

terima kasih













05 Desember 2014

AttributeError: 'NoneType' object has no attribute '_table'

Bismillahirrahmaanirrahiim

Pernah mengalami error seperti judul di atas saat uninstal/upgrade modul??
hal tersebut terjadi karena ada 1 atau lebih modul yang lupa didaftarkan dalam informasi depends di __openerp__.py

    'depends': ['mro','account_asset','mi_fleet','hr'],



pastikan semua inheritance class yang kita buat, sudah didaftarkan nama modulnya di baris depends tersebut yaa.


penyebab lainnya, pastinya karena ada modul yang belum kita tambahkan di addons kita, tapi terdaftar di depends tersebut.
ini biasanya kejadian kalo kita abis pindahan server ... terus ada aja yg terlewat..





begitu.. sekian..
semoga membantu

04 November 2014

Menambah Messaging pada Suatu Form existing

Bismillahirrahmaanirrahiim

messaging itu maksudnya form discussion  yang ada di bawah itu. yang ada add follower, lalu kita bisa diskusi di box nya.

Contoh ya form Sales Order/Invoice dll

Gak semua ada messaging, nah kalau mau menambahkan ke form yang sudah ada bagaimana? contoh kee form Product Category

Simple aja...

cukup buat suatu modul kecil, lalu tambahkan inherit ke mail.thread

seperti ini:

class product_category(osv.osv):
    _name = "product.category"
    _inherit = ["product.category", 'mail.thread']
    _description = "Add messaging on product category"
   
product_category()


Lalu di xml nya hanya tambahkan satu div di bawah seperti ini:

...
<xpath expr="/form/sheet" position="after">
  <div class="oe_chatter">
     <field name="message_follower_ids" widget="mail_followers"/>
     <field name="message_ids" widget="mail_thread" options='{"thread_level": 1}'/>
  </div> 

</xpath>


Sudah deh..
selamat mencoba

16 Oktober 2014

[Workflow] Tentang Split Mode dan Join Mode

Bismillahirrahmaanirrahiim

Alhamdulillah, akhirnya tercerahkan juga... begini nih kalo belajar otodidak dan cuma riset dari source code... dan tidak ada teman diskusi yang bisa dicolek2 (sabun kalii) plus suka lupaa (males) untuk cari manual nya duluu... 

Jadi, ceritanya beberapa kali bikin workflow suka mentok, tiba2 transisi dari activity 1 ke activity lain tidak berjalan...

Lalu, ketika baca ini https://doc.odoo.com/trunk/server/workflows/ bagian Split Mode dan Join Mode.
tiba2 tercerahkan yuhuuuuuuu

Penjelasan Singkatnya begini:

SPLIT MODE adalah  kondisi ketika transisi pergi meninggalkan suatu node activity. (panah keluar dari node). Ada 3 mode di sini: OR, XOR dan AND.
OR = semua transisi akan dicek kondisinya. Semua kondisi bernilai True akan dijalankan.
Saya kasih contoh ya: ketika di Workflow Purchase Order maka ada 2 kondisi yang dicek, yang berhubungan dengan:
1. Pembuatan Incoming Shipment
2. Pembuatan Invoice

XOR = kondisi True pertama yang dipenuhi akan dijalankan. Yang lain tidak akan dicek kembali.
Contoh kembali di Purchase Order:
Jika barang merupakan barang stockable  (bukan service), maka akan pindah ke activity picking untuk melakukan pembuatan incoming Shipment
Jika barang bukan barang stockable (seperti service), maka pengiriman dianggap selesai dan masuk ke activity picking_done
Kondisi XOR adalah kondisi default, jadi kalau gak di define di xml otomatis akan pakai kondisi XOR.

AND = semua kondisi harus bernilai True sebelum bisa menuju activity tujuan.
Nah kalau yang ini saya belum pernah nemu nih contohnya.. belum kepikiran jugaa... kalau ada ide, monggo disampaikan ya :)
Karena saya pikir2 kalau memang harus AND juga kan bisa digabungkan dalam suatu function condition ya..

Selanjutnyaa...

JOIN MODE adalah kondisi ketika transisi menuju suatu node (panah menuju node). Di sini hanya ada 2 mode yaitu XOR dan AND
Penjelasan XOR dan AND sama aja kok dengan split. tapi kenapa gak ada OR ya? yaa namanya juga JOIN ke suatu node. jadi tujuannya cuma 1 kan.. 

Lalu gimana penerapannya?
Kalau mau coba2 edit dari workflownya, bisa click suatu node activity, maka  akan muncul form dengan field Split Mode dan JOin Mode yang bisa dipilih.
Kalau mau dari xml bisa lihat contoh berikut:

        <record id="purchase.act_router" model="workflow.activity">
            <field name="wkf_id" ref="purchase.purchase_order"/>
            <field name="name">router</field>
            <field name="split_mode">OR</field>            <field name="kind">function</field>
            <field name="join_mode">XOR</field>            <field name="action">wkf_approve_order()</field>
        </record>

Kebeulan contohnya ada di node activity act_router di workflow purchase.
Aslinya adalah:

        <record id="act_router" model="workflow.activity">
            <field name="wkf_id" ref="purchase_order"/>
            <field name="name">router</field>
            <field name="split_mode">OR</field>
            <field name="kind">function</field>
            <field name="join_mode">AND</field>            <field name="action">wkf_approve_order()</field>
        </record>

Saya bold bagian join_mode yang membuat kekacauan selama ini :D
dipakai AND, yang artinya jika semua kondisi transition terpenuhi, baru bisa menuji activity router.

Oke aslinya memang yang menuju router hanya 1 transisi,
tapi ketika saya mau menambahkan 1 lagi transisi menjadi 2 transisi, akhirnya router ini tidak pernah dicapai, karena tidak mungkin 2 kondisi tersebut terpenuhi bersamaan?
Bisa cek contoh workflow yang saya buat di sini


Ada 2 transisi menuju router (JOIN MODE)
2 transisi itu berasal dari 2 activity yang berbeda setelah melalui serangkaian transisi yang berbeda untuk sampai ke smcus_case1 dan approve2 ..
Jika yang dipakai di JOIN MODE adalah AND yaa gak akan sampai ke router. karena tidak mungkin ke-2nya bernilai True. maka yang dipakai adalah XOR, karena itu saya replace acivity router dengan mengganti menjadi XOR

Sedangkan untuk SPLIT MODE yang dipakai sudah benar yaitu OR, karena harus mencek 4 kondisi yang berhubungan dengan picking dan invoice, seperti penjelasan saya sebelumnya.

Jadi, begitu deh...

Semoga bisa bermanfaat .

Happy coding ^.^


16 September 2014

Menggunakan Filter AND atau OR

Bismillahirrahmaanirrahiim

Ini hal kecil yang baru saya sadari malam ini...
Awalnya Filter di OE 7.0 ini hanya bisa pakai OR...
tapi ternyata bisa pakai AND...
dan trick nya benar2 simple,

hanya menambahkan separator -__'-

Contoh:

Nah cek bagian
<filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
<filter string="Consumable" name="consumable" icon="terp-accessories-archiver" domain="[('type','=','consu')]" help="Consumable products"/>
<separator/>
<filter string="Can be Sold" name="filter_to_sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/>

Filter di atas menunjukan filter
untuk (Services OR Consumable)  AND Can Be Sold 
Jadi, hanya dengan menambahkan <separator/> 
menjadikan query filter dengan clause AND...

Contoh gambar berikut, ada 3 AND condition
Jadi kira2 begini:
(Services OR Products OR Consumable) AND (To Purchase OR Can be SOld OR Can be Purchased) AND Available.

Kalau OR Filter nya dempet seperti Can be Sold OR To Purchase,
Sedangkan AND Filter nya dipisah..



Kira-kira begitu...
Selamat mencoba... 

CMIIW

03 September 2014

Merubah Default Calendar View Menjadi Weekly Calendar

Bismillahirrahmaanirrahiim

Ini info simple aja ...
kalau mau membuat default calendar view yang tadinya Monthly menjadi Weekly seperti gambar berikut:

maka cukup tambahkan atribut mode="week" di dalam tag calendar seperti contoh ini:

        <record id="maintenance_by_template_calendar" model="ir.ui.view">
            <field name="name">maintenance.by.template.calendar</field>
            <field name="model">maintenance.by.template</field>
            <field name="arch" type="xml">
                <calendar string="Maintenance" mode="week" color="state" date_start="date">
                    <field name="machine_id"/>
                    <field name="location"/>
                    <field name="name"/>
                </calendar>
            </field>
        </record>

begitu... sekian :)

03 Agustus 2014

Tentang perhitungan stock

Bismillahirrahmaanirrahiim

Udah lama gak update blog ini...
Ini mau bahas perhitungan stock...

Dikarenakan ada request untuk membuat modul yang menampilkan tree product dengan data future stock 7 minggu ke depan, maka saya harus memperhatikan dengan seksama method perhitungan stock di OpenERP.

Method nya ada di modul stock/product/product.py
def _product_available

yang di dalamnya memanggil method
def get_product_available

7 minggu ke depan maksudnya..
contoh hari ini tanggal 3 agustus adalah minggu ke 32,
maka saya harus menampilkan
jumlah stock saat ini, future stock minggu ke-32, minggu ke-33 sampai minggu ke-38

untuk jumlah stock saat ini tidak masalah, karena memang menghitung dari tabel stock_move dengan state 'done'

nah saat menghitung future stock ada keanehan (setidaknya menurut saya aneh, mohon dikoreksi ya)

contoh:
ada PO utk product X tanggal 03/08 dengan expected delivery tanggal 25 agustus (minggu ke-35) dengan jumlah 15
Stock saat ini adalah 20

maka yang saya harapkan adalah
current stock = 20
future stock minggu-32 = masih 20
future stock minggu-33 = masih 20
future stock minggu-34 = masih 20 
future stock minggu-35 = baru berubah menjadi 35

ehh tapi hasilnyaaa....
current stock = 20
future stock minggu-32 = 35
future stock minggu-33 = 35
future stock minggu-34 = 35
future stock minggu-35 = 35

kenapa hasilnya seperti itu?
karena di method
    def get_product_available(self, cr, uid, ids, context=None):

ada baris berikut:

        if from_date and to_date:
            date_str = "date>=%s and date<=%s"
            where.append(tuple([from_date]))
            where.append(tuple([to_date]))
        elif from_date:
            date_str = "date>=%s"
            date_values = [from_date]
        elif to_date:
            date_str = "date<=%s"
            date_values = [to_date]
        if date_values:
            where.append(tuple(date_values))

Maksudnya adalah, dia akan menghitung stock dari table stock_move dengan where clause (jika ada filter date) adalah where stock_move.date >= from_date and date <= to_date dst
sedangkan field date sendiri digunakan untuk menyimpan tanggal order (tanggal dibuatnya IS - dari tanggal PO) dan jika sudah done maka field date adalah tanggal dikirimkan/diterimanya barang.

Sedangkan future stock harusnya diambil dari date_expected nya dongs... 

jadi where stock_move.date_expected >= blablabla

Karena itu saya lakukan perubahan hmm 'lumayan sedikit #eeh' di method tsb seperti ini kira2..



jadi saya bagi-2
yg pertama utk states done saja pakai yang biasa
yang satu lagi selain done diambil dari date_expected

Mohon bantu review dan dikoreksi jika ada salah atau disederhanakan

terima kasihhh

30 Januari 2014

Your OpenERP is not supported -> Upgrade or register your contract here

Bismillahirrahmaanirrahiim

Ini pertanyaan yang cukup sering masuk ke email saya (*gaya benerr*) haha
Dan yang membuat beberapa orang mundur untuk pakai OpenERP 7.0

Kalau OpenERP 7.0 versi awal2 sih gak ada, tapi yang terbaru (saya coba januari 2014) ada,
terus apakah artinya itu? ya hanya notification aja sih kalau yang kita pakai memang versi tak berbayar dan artinya kalau ada apa2 ya resiko sendiri dann komunitas :D



Ganggu lho tulisan tersebut..
yasudah disembunyikan saja...

bagaimana caranya?
cukup edit 1 baris saja...
di addons/mail/__openerp__.py
komen saja baris 96

#'static/src/xml/announcement.xml'

save lalu restart OpenERP, maka hilanglah tulisan tersebut.

Demikian,
Semoga bermanfaat

21 Januari 2014

Metode pembayaran invoice dengan 2 currency

Bismillahirrahmaanirrahiim

Contoh ada Customer Invoice USD dengan nilai 100 dan pajak 10 USD
Seperti gambar berikut:


Lalu customer akan membayar:
  • 100 USD dalam USD
  • tax 10 USD dalam IDR
Pembayaran pertama 100 USD
Untuk pembayaran 100 USD dapat menggunakan register payment biasa. 
Contohnya seperti ini.



Pembayaran 10 USD dalam IDR

Sedangkan untuk pembayaran 10 USD dalam IDR, contohnya 10 USD = 120.000 saat pembayaran terjadi.
Kita gunakan menu Customer Payments
Sisa yang belum dibayar sebenarnya hanya 100.000 (sesuai kurs saat validasi invoice terjadi), tapi customer membayar 120.000 sesuai tanggal pembayaran. Maka ada selisih 20.000 yang bisa dijadikan sebagai account pendapatan selisih kurs

Contohnya sebagai berikut:

Nah lihat contoh di atas
masukan Paid Amount 120.000
Kemudian klik full reconcile di baris item Credits
Kamudian pilih Payment Differece (di bawah) Reconcile Payment Balance dengan COunterpart Account Pendapatan Selisih Kurs
Lalu Validate deh...

Kembali ke invoice, maka state nya sudah Paid.

Ohya, kenapa gak bayar 10 USD dalam IDR nya melalui tombol Register Payment? ya karena di wizard tersebut tidak ada fasilitas reconcile payment balance nya..
paling kalau kelebihan sih ada, tapi kalo kurang dari nilai yang seharusnya tidak dimunculkan di wizard tersebut... Silahkan dicustomize jika mau membuatnya lebih simple hehe

Semoga bermanfaat..