shop payment

conv_bal
watcha.h 2015-02-04 15:51:14 +07:00
parent 3b6da8c247
commit 27b95b6d77
12 changed files with 329 additions and 34 deletions

View File

@ -3,4 +3,11 @@
<field name="view_cls">multi_view</field> <field name="view_cls">multi_view</field>
<field name="model">clinic.shop</field> <field name="model">clinic.shop</field>
<field name="menu">clinic_menu</field> <field name="menu">clinic_menu</field>
<field name="tabs">[
["All",[]],
["Draft",[["state","=","draft"]]],
["Paid",[["state","=","paid"]]],
["Cancelled",[["state","=","cancelled"]]]
]
</field>
</action> </action>

View File

@ -0,0 +1,5 @@
<action>
<field name="type">method</field>
<field name="model">clinic.shop</field>
<field name="method">view_payment</field>
</action>

View File

@ -38,5 +38,9 @@
<field name="patient_type_id"/> <field name="patient_type_id"/>
<field name="imp_patient_type_id"/> <field name="imp_patient_type_id"/>
</tab> </tab>
<tab string="Accounting">
<field name="cash_account_id"/>
<field name="income_account_id" string="Account Receivable"/>
</tab>
</tabs> </tabs>
</form> </form>

View File

@ -1,20 +1,21 @@
<form model="clinic.shop"> <form model="clinic.shop" attrs='{"readonly":[["state","in",["cancelled","paid","waiting_payment"]]]}' show_company="1">
<head> <head>
<field name="state"/> <field name="state"/>
<button string="Options" dropdown="1"> <button string="Options" dropdown="1">
<item string="Copy"/> <item string="To Draft" method="to_draft" states="paid"/>
</button> </button>
</head> </head>
<group form_layout="stacked"> <group form_layout="stacked">
<field name="number" span="2"/> <field name="number" span="2"/>
<field name="ref" span="2"/>
<field name="date" span="2"/>
<field name="patient_id" span="2" onchange="onchange_patient"/> <field name="patient_id" span="2" onchange="onchange_patient"/>
<field name="contact_id" required='1' span="2"/> <field name="contact_id" required='1' span="2"/>
<field name="ref" span="2"/>
<field name="date" span="2"/>
<field name="branch_id" span="2"/> <field name="branch_id" span="2"/>
<field name="department_id" domain='[["branch_id","=",branch_id]]' span="2"/> <field name="department_id" domain='[["branch_id","=",branch_id]]' span="2"/>
<field name="related_id" span="3"/> <field name="hd_case_call" invisible="1"/>
<field name="shop_categs" invisible="1"/> <field name="shop_categs" invisible="1"/>
<field name="company_id" invisible="1"/>
<tabs> <tabs>
<tab string="General"> <tab string="General">
<field name="lines" nolabel="1"> <field name="lines" nolabel="1">
@ -35,19 +36,19 @@
</group> </group>
</tab> </tab>
<tab string="Other"> <tab string="Other">
<group form_layout="stacked"> <field name="related_id" span="3"/>
<field name="user_id" span="3"/> <field name="user_id" span="3"/>
</group> <field name="pay_type" span="3"/>
</tab> </tab>
</tabs> </tabs>
</group> </group>
<foot> <foot>
<button string="Cash" method="pay_cash" type="success"/> <button string="Cash" method="pay_cash" states="draft" type="success"/>
<button string="Credit" method="pay_credit" type="default"/> <button string="Credit" method="pay_credit" states="draft" type="default"/>
</foot> </foot>
<related> <related>
<field name="invoices"/> <field name="invoices"/>
<field name="payments"> <field name="payments" click_action="clinic_shop_view_payment">
<list> <list>
<field name="number"/> <field name="number"/>
<field name="date"/> <field name="date"/>

View File

@ -1,10 +1,12 @@
<list model="clinic.shop"> <list model="clinic.shop" colors='{"#cfc":[["state","=","paid"]],"#f9e37d":[["state","=","waiting_payment"]],"#bcbbb9":[["state","=","cancelled"]],"#ACD1E9":[["state","=","waiting_payment"]]}'>
<field name="number"/> <field name="number"/>
<field name="date"/> <field name="date"/>
<!--<field name="patient_id"/>-->
<field name="contact_id"/> <field name="contact_id"/>
<field name="ref"/>
<field name="branch_id"/> <field name="branch_id"/>
<field name="department_id"/> <field name="department_id"/>
<field name="pay_type"/>
<field name="related_id"/>
<field name="user_id"/> <field name="user_id"/>
<field name="state"/> <field name="state"/>
</list> </list>

View File

@ -1,8 +1,8 @@
<inherit model="settings" inherit="fin_settings"> <inherit model="settings" inherit="fin_settings">
<field name="rounding_account_id" position="after"> <!--<field name="rounding_account_id" position="after">-->
<separator string="Clinic (Patient pay by them-self)"/> <!--<separator string="Clinic (Patient pay by them-self)"/>-->
<field name="cash_account_id" domain="[['type','!=','view']]"/> <!--<field name="cash_account_id" domain="[['type','!=','view']]"/>-->
<field name="income_account_id" domain="[['type','!=','view']]"/> <!--<field name="income_account_id" domain="[['type','!=','view']]"/>-->
<!--<field name="ap_doctor_id"/>--> <!--<field name="ap_doctor_id"/>-->
</field> <!--</field>-->
</inherit> </inherit>

View File

@ -46,6 +46,7 @@ from . import gen_visit_line
from . import gen_visit_time from . import gen_visit_time
from . import payment from . import payment
from . import account_payment from . import account_payment
from . import account_payment_line
from . import account_invoice from . import account_invoice
from . import account_invoice_line from . import account_invoice_line
from . import staff from . import staff

View File

@ -0,0 +1,13 @@
import time
from netforce.model import Model, fields, get_model
class AccountPaymentLine(Model):
_inherit="account.payment.line"
_fields={
'ar_credit_id': fields.Many2One("account.account","Account Credit"), # no long use
"ar_debit_id": fields.Many2One("account.account","Account Debit"), # no long use
}
AccountPaymentLine.register()

View File

@ -308,7 +308,7 @@ class HDCase(Model):
partner=obj.patient_id.partner_id partner=obj.patient_id.partner_id
if not partner: if not partner:
raise Exception("Not partner") raise Exception("Not partner")
st=get_model('settings').browse(1) st=get_model('clinic.setting').browse(1)
cash_account_id=st.cash_account_id.id cash_account_id=st.cash_account_id.id
income_account_id=st.income_account_id.id income_account_id=st.income_account_id.id
@ -1202,6 +1202,7 @@ class HDCase(Model):
def new_shop(self,ids,context={}): def new_shop(self,ids,context={}):
return { return {
'next': { 'next': {
'hd_case_call': True,
'refer_id': ids[0], 'refer_id': ids[0],
'name': 'clinic_popup_shop', 'name': 'clinic_popup_shop',
} }

View File

@ -31,6 +31,8 @@ class ClinicSetting(Model):
'branch_id': fields.Many2One("clinic.branch","Branch"), 'branch_id': fields.Many2One("clinic.branch","Branch"),
'shop_categs': fields.Many2Many("product.categ","Categs"), 'shop_categs': fields.Many2Many("product.categ","Categs"),
'shop_type_id': fields.Many2One("clinic.patient.type","Patient Type"), 'shop_type_id': fields.Many2One("clinic.patient.type","Patient Type"),
"cash_account_id": fields.Many2One("account.account","Cash Account",multi_company=True),
"income_account_id": fields.Many2One("account.account","Income Account",multi_company=True),
} }
_defaults={ _defaults={
@ -120,8 +122,6 @@ class ClinicSetting(Model):
prod.write({ prod.write({
'patient_types': [('add',tids)] 'patient_types': [('add',tids)]
}) })
print("Done!")
return
for line in obj.account_products: for line in obj.account_products:
acc=line.ar_debit_id acc=line.ar_debit_id
@ -132,8 +132,8 @@ class ClinicSetting(Model):
line.write({ line.write({
'type': type, 'type': type,
}) })
print("Done!")
return print("Update product completed!")
for vs in get_model("clinic.visit").search_browse([['state','in', ['draft','pending']],['doctor_id','=',None]]): for vs in get_model("clinic.visit").search_browse([['state','in', ['draft','pending']],['doctor_id','=',None]]):
doctor=vs.patient_id.doctor_id doctor=vs.patient_id.doctor_id
if doctor: if doctor:
@ -141,6 +141,12 @@ class ClinicSetting(Model):
'doctor_id': doctor.id, 'doctor_id': doctor.id,
}) })
print("update visit.date ", vs.visit_date) print("update visit.date ", vs.visit_date)
print("Update visit completed!")
for shop in get_model("clinic.shop").search_browse([]):
shop.write({
'company_id': 1,
})
print("Update shop completed!")
print("Done! ") print("Done! ")
def reset_last_import(self,ids,context={}): def reset_last_import(self,ids,context={}):

View File

@ -1,12 +1,14 @@
import time import time
from netforce.model import Model, fields, get_model from netforce.model import Model, fields, get_model
from netforce.access import get_active_user, set_active_user from netforce.access import get_active_user, set_active_user, get_active_company
from netforce.utils import get_data_path from netforce.utils import get_data_path
class Shop(Model): class Shop(Model):
_name="clinic.shop" _name="clinic.shop"
_string="Shop" _string="Shop"
_name_field="number"
_multi_company=True
def _get_all(self,ids,context={}): def _get_all(self,ids,context={}):
res={} res={}
@ -29,8 +31,8 @@ class Shop(Model):
'date': fields.Date("Date",search=True), 'date': fields.Date("Date",search=True),
'patient_id': fields.Many2One('clinic.patient','Patient',search=True), 'patient_id': fields.Many2One('clinic.patient','Patient',search=True),
'contact_id': fields.Many2One('partner','Contact',search=True), 'contact_id': fields.Many2One('partner','Contact',search=True),
'department_id': fields.Many2One("clinic.department","Department"), 'department_id': fields.Many2One("clinic.department","Department",search=True),
'branch_id': fields.Many2One("clinic.branch","Branch"), 'branch_id': fields.Many2One("clinic.branch","Branch",search=True),
'lines': fields.One2Many('clinic.shop.line','shop_id','Lines'), 'lines': fields.One2Many('clinic.shop.line','shop_id','Lines'),
'total': fields.Float("Total",function="_get_all",function_multi=True), 'total': fields.Float("Total",function="_get_all",function_multi=True),
'user_id': fields.Many2One("base.user","Pharmacist"), 'user_id': fields.Many2One("base.user","Pharmacist"),
@ -41,6 +43,9 @@ class Shop(Model):
'dom_str': fields.Char("Dom Str"), 'dom_str': fields.Char("Dom Str"),
'shop_categs': fields.Many2Many("product.categ","Categs",function="_get_all",function_multi=True,store=True), 'shop_categs': fields.Many2Many("product.categ","Categs",function="_get_all",function_multi=True,store=True),
"related_id": fields.Reference([["sale.order","Sales Order"],["purchase.order","Purchase Order"],["project","Project"],["job","Service Order"],["service.contract","Service Contract"]],"Related To"), "related_id": fields.Reference([["sale.order","Sales Order"],["purchase.order","Purchase Order"],["project","Project"],["job","Service Order"],["service.contract","Service Contract"]],"Related To"),
'company_id': fields.Many2One("company","Company"),
"pay_type": fields.Selection([("cash","Cash"),("credit","Credit")],"Pay Type"),
'hd_case_call': fields.Boolean("HD Case Call"),
} }
def _get_branch(self,context={}): def _get_branch(self,context={}):
@ -72,6 +77,22 @@ class Shop(Model):
patient_id=hd_case.patient_id.id patient_id=hd_case.patient_id.id
return patient_id return patient_id
def _get_contact(self,context={}):
partner_id=None
if context.get('refer_id'):
refer_id=context.get("refer_id")
hd_case=get_model("clinic.hd.case").browse(refer_id)
patient=hd_case.patient_id
partner=patient.partner_id
partner_id=partner.id
return partner_id
def _get_hdcase_call(self,context={}):
res=False
if context.get('hd_case_call'):
res=True
return res
def _get_number(self,context={}): def _get_number(self,context={}):
while 1: while 1:
seq_id=get_model("sequence").find_sequence(name="Clinic RD Shop") seq_id=get_model("sequence").find_sequence(name="Clinic RD Shop")
@ -90,12 +111,16 @@ class Shop(Model):
'number': '/', 'number': '/',
'date': lambda *a: time.strftime("%Y-%m-%d"), 'date': lambda *a: time.strftime("%Y-%m-%d"),
'user_id': lambda *a: get_active_user(), 'user_id': lambda *a: get_active_user(),
'company_id': lambda *a: get_active_company(),
'branch_id': _get_branch, 'branch_id': _get_branch,
'department_id': _get_department, 'department_id': _get_department,
'state': 'draft', 'state': 'draft',
'shop_categs': _get_shop_categs, 'shop_categs': _get_shop_categs,
'related_id': _get_related, 'related_id': _get_related,
'patient_id': _get_patient, 'patient_id': _get_patient,
'contact_id': _get_contact,
'pay_type': 'cash',
'hd_case_call': _get_hdcase_call,
} }
def update_all(self,context={}): def update_all(self,context={}):
@ -160,7 +185,7 @@ class Shop(Model):
obj=self.browse(ids)[0] obj=self.browse(ids)[0]
active_id=obj.id active_id=obj.id
action="clinic_shop" action="clinic_shop"
if obj.related_id: if obj.hd_case_call:
active_id=obj.related_id.id active_id=obj.related_id.id
action="clinic_hd_case" action="clinic_hd_case"
st=get_model("clinic.setting").browse(1) st=get_model("clinic.setting").browse(1)
@ -170,6 +195,7 @@ class Shop(Model):
obj.write({ obj.write({
'number': self._get_number(), 'number': self._get_number(),
}) })
obj.make_invoices()
return { return {
'next': { 'next': {
'name': action, 'name': action,
@ -183,7 +209,7 @@ class Shop(Model):
obj=self.browse(ids)[0] obj=self.browse(ids)[0]
active_id=obj.id active_id=obj.id
action="clinic_shop" action="clinic_shop"
if obj.related_id: if obj.hd_case_call:
active_id=obj.related_id.id active_id=obj.related_id.id
action="clinic_hd_case" action="clinic_hd_case"
st=get_model("clinic.setting").browse(1) st=get_model("clinic.setting").browse(1)
@ -191,8 +217,9 @@ class Shop(Model):
raise Exception("Please defind Shop Type on menu Clinic Settings -> RD Shop") raise Exception("Please defind Shop Type on menu Clinic Settings -> RD Shop")
if obj.number=="/": if obj.number=="/":
obj.write({ obj.write({
'number': self._get_number() 'number': self._get_number(),
}) })
obj.make_payment()
return { return {
'next': { 'next': {
'name': action, 'name': action,
@ -202,4 +229,235 @@ class Shop(Model):
'flash': 'Pay Successfully', 'flash': 'Pay Successfully',
} }
def make_invoices(self,ids,context={}):
setting=get_model("settings").browse(1,context)
cst=get_model("clinic.setting").browse(1)
shop_type=cst.shop_type_id
currency_id=setting.currency_id.id
if not currency_id:
raise Exception("Currency not found in account settings")
company_id=get_active_company()
uom=get_model("uom").search_browse([['name','ilike','%Unit%']])
if not uom:
raise Exception("Unit not found in uom")
obj=self.browse(ids[0])
if obj.invoices:
for inv in obj.invoices:
inv.void()
due_date=obj.date[1:10] # XXX
context['type']='out'
context['inv_type']='invoice'
cst=get_model('clinic.setting').browse(1)
prod_acc=cst.get_product_account
partner=obj.contact_id
vals={
"type": "out",
"inv_type": "invoice",
"tax_type": "tax_in",
'due_date': due_date,
"ref": obj.number or "",
'department_id': obj.department_id.id,
"related_id": "clinic.shop,%s"%obj.id,
"currency_id": currency_id,
"company_id": company_id,
'partner_id': partner.id,
"lines": [],
}
for line in obj.lines:
if line.amount < 1:
continue
prod=line.product_id
acc=prod_acc(prod.id,shop_type.id,'credit')
account_id=acc.get("ar_credit_id",None)
ar_debit_id=acc.get("ar_debit_id",None)
if not account_id:
raise Exception("No Income Credit Account for product [%s] %s"%(prod.code, prod.name))
if not ar_debit_id:
raise Exception("No Ar Debit Account for product [%s] %s"%(prod.code, prod.name))
vals['lines'].append(('create',{
"product_id": prod.id,
"description": line.description or "",
"qty": line.qty,
"uom_id": line.uom_id.id,
"unit_price": line.price or 0,
"amount": line.amount or 0,
'account_id': account_id,
'ar_debit_id': ar_debit_id,
}))
inv_id=get_model("account.invoice").create(vals,context)
inv=get_model("account.invoice").browse(inv_id)
inv.post()
obj.make_pickings()
obj.write({
'state': 'paid',
'pay_type': 'credit',
})
def make_pickings(self,ids,context={}):
obj=self.browse(ids[0])
partner=obj.contact_id
# no picking
if not obj.lines:
return
ship_address_id=None
for address in partner.addresses:
if address.type=="shipping":
ship_address_id=address.id
break
if not ship_address_id:
raise Exception("No shipping address for contact %s"%partner.name)
# default journal
cust_loc_id=None
wh_loc_id=None
# find location
# 1. from department -> branch -> stock journal -> from, to
department=obj.department_id
if department:
stock_journal=department.pick_out_journal_id
if stock_journal:
wh_loc_id=stock_journal.location_from_id.id
cust_loc_id=stock_journal.location_to_id.id
pick_vals={
"type": "out",
'journal_id': stock_journal.id,
"ref": obj.number,
"related_id": "clinic.shop,%s"%obj.id,
"partner_id": partner.id,
"ship_address_id": ship_address_id,
"state": "draft",
"lines": [],
}
if not cust_loc_id:
res=get_model("stock.location").search([["type","=","customer"]])
if not res:
raise Exception("Customer location not found!")
cust_loc_id=res[0]
for line in obj.lines:
if line.qty < 1:
continue
prod=line.product_id
if prod.type != 'stock':
continue
if not wh_loc_id:
wh_loc_id=prod.location_id.id
if not wh_loc_id:
res=get_model("stock.location").search([["type","=","internal"]])
if not res:
raise Exception("Warehouse not found")
wh_loc_id=res[0]
line_vals={
"product_id": prod.id,
"qty": line.qty,
"uom_id": prod.uom_id.id,
"location_from_id": wh_loc_id,
"location_to_id": cust_loc_id,
}
pick_vals["lines"].append(("create",line_vals))
if not pick_vals["lines"]:
return {
"flash": "Nothing left to deliver",
}
picking_obj=get_model("stock.picking")
pick_id=picking_obj.create(pick_vals,context={"pick_type": "out"})
pick=picking_obj.browse(pick_id)
pick.set_done([pick_id])
def make_payment(self,ids,context={}):
obj=self.browse(ids)[0]
partner=obj.contact_id
cst=get_model('clinic.setting').browse(1)
shop_type=cst.shop_type_id
cash_account_id=cst.cash_account_id.id
income_account_id=cst.income_account_id.id
if not cash_account_id:
raise Exception("No Cash Account")
if not income_account_id:
raise Exception("No Income Account")
company_id=get_active_company()
vals={
"partner_id": partner.id,
"company_id": company_id,
"type": "in",
"pay_type": "direct",
'date': time.strftime("%Y-%m-%d"),
"account_id": cash_account_id,
'related_id': "clinic.shop,%s"%obj.id,
'ref': obj.number,
'direct_lines': [],
}
prod_acc=cst.get_product_account
for line in obj.lines:
prod=line.product_id
acc=prod_acc(prod.id,shop_type.id,'cash')
account_id=acc.get("ar_credit_id",None)
ar_debit_id=acc.get("ar_debit_id",None)
if not account_id:
raise Exception("No Income Credit Account for product [%s] %s"%(prod.code, prod.name))
if not ar_debit_id:
raise Exception("No Ar Debit Account for product [%s] %s"%(prod.code, prod.name))
desc="[%s] %s"%(prod.code, line.description or "")
vals['direct_lines'].append(('create',{
"description": desc,
"qty": line.qty,
"unit_price": line.price or 0,
"amount": line.amount or 0,
'account_id': account_id,
}))
payment_id=get_model("account.payment").create(vals,context={"type":"in"})
payment=get_model('account.payment').browse(payment_id)
payment.post()
obj.make_pickings()
obj.write({
'state': 'paid',
'pay_type': 'cash',
})
def to_draft(self,ids,context={}):
for obj in self.browse(ids):
for payment in obj.payments:
payment.to_draft()
payment.delete()
for inv in obj.invoices:
inv.write({
'state': 'draft',
})
if inv.move_id:
inv.move_id.to_draft()
inv.move_id.delete()
inv.delete()
for picking in obj.pickings:
picking.to_draft()
picking.delete()
obj.write({
'state': 'draft',
})
if obj:
return {
'next': {
'name': {
'next': 'clinic_shop',
'mode': 'form',
'active_id': obj.id,
},
'flash': '%s has been set to draft'%obj.number or "",
}
}
def view_payment(self,ids,context={}):
return {
'next': {
'name': 'payment',
'mode': 'form',
'active_id': ids[0],
},
}
Shop.register() Shop.register()

View File

@ -1,8 +1,8 @@
todo: todo:
- sale medicine ***
- payment
- matching payment *** - matching payment ***
- script generate hd case - script generate hd case
- sale medicine -> ok
- payment
- accounting - accounting
- labor cost - labor cost
- report ->ok - report ->ok
@ -14,9 +14,6 @@ todo:
- if user select product by them self -> testing - if user select product by them self -> testing
- credit <= product -> tab -> accounting -> sale -> sale account - credit <= product -> tab -> accounting -> sale -> sale account
- debit <= 1. contact -> tab accounting -> account receiaveble , 2. finacial setting -> account receiable - debit <= 1. contact -> tab accounting -> account receiaveble , 2. finacial setting -> account receiable
- patient - patient
- link vascular access to patient profile and copy to hd case after confirm on visit -> ok - link vascular access to patient profile and copy to hd case after confirm on visit -> ok
- can update date from hd case to patient - can update date from hd case to patient