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..

11 Desember 2013

Mohon maaf..

Bismillahirrahmaanirrahiim

Dear all, mohon maaf untuk komen2 yang belum sempat saya jawab.
DIkarenakan kondisi saya yang baru punya baby (udah 2 bulan sii), jadi gak sempet update2 blog ini..
Jadi, kalau ada pertanyaan, bisa email saya saja yaa..
ke siti.mawaddah@gmail.com

Terima kasih banyakk

29 Agustus 2013

Contoh Penggunaan attribut on_change dalam fields

Bismillahirrahmaanirrahiim

Tadi pagi ada yang email nanya sehubungan dengan attribut on_change..
Monggo dicoba.. ini blind code sii.. saya gak nyobain ... mudah2an gak ada yang salah...
kalau ada yang salah baru saya cobain :D

Contoh:
kita punya 3 field dengan tipe char:
field1
field2
field3

dan 1 field yang diharapkan berisi gabungan dari ketiga field di atas. Sebutlah nama fieldnya:
field_gab

Jadi contoh:
di form kita isi field berikut:
field1 = "aku"
field2 = "adalah"
field3 = "saya"

maka harapannya field_gab akan otomatis berisi: "aku adalah saya" dan perubahan isi dari ke-3 field akan otomatis meng-update field_gab tersebut.

bagaimana caranya?
manfaatkan attribut on_change

jadi di form view kita set atribut dari ke-4 field di atas.


kemudian di pythonnya kita buat method onchange_fields:

udah deh selesai.. cona direstart dan diupgrade modulnya...
ohya kenapa field_gab musti ditambahkan on_change juga?
agar tidak dimungkinkan dilakukan perubahan terhadap field tersebut...
jadi field_gab isinya tetap konsisiten gabungan dari ke-3 field sebelumnya..

semoga bermanfaat...

26 Juli 2013

[Extra] Koneksi Database MySQL dengan Python

Bismillahirrahmaanirrahiim

  • Pastikan sudah mengintal package libmysqlclient-dev dengan:
    apt-get install libmysqlclient-dev
  • DOwnload modul MySQLdb. DOwnload dari sini 
  • Instal modul tersebut dengan cara (Pastikan login sebagai root ya):
    $ gunzip MySQL-python-1.2.2.tar.gz
    $ tar -xvf MySQL-python-1.2.2.tar
    $ cd MySQL-python-1.2.2
    $ python setup.py build
    $ python setup.py install
  • Coba deh buat satu script seperti berikut (contoh: test.py):
import MySQLdb

# Open database connection
db = MySQLdb.connect("localhost","root","password","nama_database" )

# prepare a cursor object using cursor() method
cursor = db.cursor()

# execute SQL query using execute() method.
cursor.execute("SELECT VERSION()")

# Fetch a single row using fetchone() method.
data = cursor.fetchone()

print "Database version : %s " % data

# disconnect from server
db.close()
  • Terus test deh...
    python test.py
Hasilnyaaaaaaaaa

root@mawaddah-Aspire-4750:/home/mawaddah# python test.py 
Database version : 5.1.66-0ubuntu0.11.10.3


Selesai dehhhh

referensi: http://www.tutorialspoint.com/python/python_database_access.htm