Initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
|
||||
default_app_config = 'basedata.apps.BaseDataConfig'
|
||||
@@ -0,0 +1,339 @@
|
||||
# coding=utf-8
|
||||
from django.contrib import admin
|
||||
from django.forms import models
|
||||
from django.forms import fields,TextInput,Textarea
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.contenttypes.generic import GenericTabularInline
|
||||
from common import generic
|
||||
from basedata.models import ValueList,ValueListItem,Address,Partner,BankAccount,Project,Measure,Material,Brand,\
|
||||
Category,Warehouse,TechnicalParameterName,TechnicalParameterValue,Trade,ExpenseAccount,Employee,Family,Education,\
|
||||
WorkExperience,ExtraParam,DataImport,Document
|
||||
|
||||
|
||||
class ValueListItemInline(admin.TabularInline):
|
||||
model = ValueListItem
|
||||
exclude = ['group_code']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
class ValueListAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
CODE_PREFIX = 'S'
|
||||
list_display = ['code', 'name', 'module', 'status']
|
||||
fields = (('code',),('name',),('module',),('status','init','locked',),('locked_by','lock_time',))
|
||||
raw_id_fields = ['module']
|
||||
readonly_fields = ['locked_by','lock_time']
|
||||
inlines = [ValueListItemInline]
|
||||
search_fields = ['code','name']
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
super(ValueListAdmin,self).save_model(request,obj,form,change)
|
||||
obj.valuelistitem_set.update(group_code=obj.code)
|
||||
|
||||
|
||||
class AddressAdmin(generic.BOAdmin):
|
||||
list_display = ['address','phone','contacts']
|
||||
exclude = ['content_type','object_id','creator','modifier','creation','modification','begin','end']
|
||||
|
||||
|
||||
class AddressInline(GenericTabularInline):
|
||||
model = Address
|
||||
exclude = ['content_type','object_id','creator','modifier','creation','modification','begin','end']
|
||||
extra = 1
|
||||
|
||||
|
||||
class BankAccountInline(admin.TabularInline):
|
||||
model = BankAccount
|
||||
fields = ['account','title','memo']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class PartnerForm(models.ModelForm):
|
||||
tax_address = fields.CharField(widget=TextInput(attrs={'size': 119,}),required=False,label=_("tax address"))
|
||||
memo = fields.CharField(widget=Textarea(attrs={'rows':3,'cols':85}),required=False,label=_("memo"))
|
||||
|
||||
class Meta:
|
||||
model = Partner
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class PartnerAdmin(generic.BOAdmin):
|
||||
list_display = ['code','name','partner_type','level']
|
||||
list_display_links = ['code','name']
|
||||
|
||||
fields = (('code','name',),('short','pinyin',),('partner_type','level'),('tax_num','tax_account',),
|
||||
('tax_address',),('contacts','phone',),('memo',),)
|
||||
search_fields = ['code','name','pinyin']
|
||||
form = PartnerForm
|
||||
save_on_top = True
|
||||
inlines = [AddressInline,BankAccountInline]
|
||||
|
||||
def get_queryset(self, request):
|
||||
if request.user.is_superuser or (request.user.has_perm('basedate.view_all_customer') and request.user.has_perm('basedate.view_all_supplier')):
|
||||
return super(PartnerAdmin,self).get_queryset(request)
|
||||
elif request.user.has_perm('basedata.view_all_customer'):
|
||||
return super(PartnerAdmin,self).get_queryset(request).filter(partner_type='C')
|
||||
else:
|
||||
return super(PartnerAdmin,self).get_queryset(request).filter(partner_type='S')
|
||||
|
||||
|
||||
class ProjectForm(models.ModelForm):
|
||||
income = fields.DecimalField(required=False,widget=TextInput(attrs={'readonly':'true'}))
|
||||
expand = fields.DecimalField(required=False,widget=TextInput(attrs={'readonly':'true'}))
|
||||
|
||||
class Meta:
|
||||
model = Project
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ProjectAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'PJ'
|
||||
list_display = ['code','name','status','income','expand']
|
||||
list_display_links = ['code','name']
|
||||
fields = (
|
||||
('code','name',),('short','pinyin',),
|
||||
('partner',),('status','prj_type',),
|
||||
('description',),
|
||||
('budget','income','expand',),('blueprint',),('offer',),('business',),('users',),
|
||||
)
|
||||
search_fields = ['code','name']
|
||||
readonly_fields = ['status']
|
||||
raw_id_fields = ['partner']
|
||||
filter_horizontal = ['users']
|
||||
form = ProjectForm
|
||||
|
||||
|
||||
class WarehouseAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','name','location']
|
||||
filter_horizontal = ['users']
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
super(WarehouseAdmin,self).save_model(request,obj,form,change)
|
||||
try:
|
||||
code = getattr(obj,'code')
|
||||
if not code:
|
||||
obj.code = '%s%02d' % ('A',obj.id)
|
||||
obj.save()
|
||||
except Exception,e:
|
||||
self.message_user(request,'ERROR:%s' % e,level=messages.ERROR)
|
||||
|
||||
|
||||
class BrandAdmin(admin.ModelAdmin):
|
||||
list_display = ['name','pinyin']
|
||||
|
||||
|
||||
class MeasureAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','name','status']
|
||||
|
||||
|
||||
class CategoryAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','name','path']
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
super(CategoryAdmin,self).save_model(request,obj,form,change)
|
||||
try:
|
||||
code = getattr(obj,'code')
|
||||
if not code:
|
||||
obj.code = '%s%02d' % ('F',obj.id)
|
||||
obj.save()
|
||||
if obj.parent:
|
||||
if obj.parent.path:
|
||||
obj.path = obj.parent.path + '/'+obj.parent.name
|
||||
else:
|
||||
obj.path = obj.parent.name
|
||||
obj.save()
|
||||
except Exception,e:
|
||||
self.message_user(request,'ERROR:%s' % e,level=messages.ERROR)
|
||||
|
||||
|
||||
class MaterialForm(models.ModelForm):
|
||||
name = fields.CharField(widget=TextInput(attrs={"size":"119"}),label=_("material name"))
|
||||
spec = fields.CharField(widget=TextInput(attrs={"size":"119"}),required=False,label=_("specifications"))
|
||||
|
||||
class Mata:
|
||||
model = Material
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ExtraParamInline(admin.TabularInline):
|
||||
model = ExtraParam
|
||||
fields = ['name','data_type','data_source']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class MaterialAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'IT'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','name','spec','tp']
|
||||
list_display_links = ['code','name']
|
||||
list_filter = ['brand','tp']
|
||||
search_fields = ['code','name']
|
||||
fields = (
|
||||
('code','barcode'),('name',),('spec',),
|
||||
('brand',),('category',),('status','is_equip','can_sale','is_virtual',),
|
||||
('warehouse',),('tp',),('measure',),('stock_price','purchase_price','sale_price',),
|
||||
)
|
||||
filter_horizontal = ['measure']
|
||||
inlines = [ExtraParamInline]
|
||||
form = MaterialForm
|
||||
|
||||
|
||||
class TechParamValueInline(admin.TabularInline):
|
||||
model = TechnicalParameterValue
|
||||
|
||||
|
||||
class TechParamNameAdmin(admin.ModelAdmin):
|
||||
list_display = ['name','category']
|
||||
inlines = [TechParamValueInline]
|
||||
|
||||
|
||||
class TradeAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','name','parent']
|
||||
|
||||
|
||||
class ExpenseAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'FC'
|
||||
list_display = ['code','name','category']
|
||||
list_display_links = ['code','name']
|
||||
list_filter = ['category']
|
||||
search_fields = ['name']
|
||||
|
||||
|
||||
class FamilyForm(models.ModelForm):
|
||||
name = fields.CharField(widget=TextInput(attrs={"size":"25"}),label=_("name"))
|
||||
phone = fields.CharField(widget=TextInput(attrs={"size":"25"}),label=_("phone"))
|
||||
|
||||
class Meta:
|
||||
model = Family
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class FamilyInline(admin.TabularInline):
|
||||
model = Family
|
||||
exclude = ['creator','modifier','creation','modification','begin','end']
|
||||
form = FamilyForm
|
||||
extra = 1
|
||||
|
||||
|
||||
class EducationInline(admin.TabularInline):
|
||||
model = Education
|
||||
exclude = ['creator','modifier','creation','modification']
|
||||
extra = 0
|
||||
|
||||
|
||||
class WorkExperienceInline(admin.TabularInline):
|
||||
model = WorkExperience
|
||||
exclude = ['creator','modifier','creation','modification']
|
||||
extra = 1
|
||||
|
||||
|
||||
class EmployeeAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = '1'
|
||||
list_display = ['code','name','position','gender','idcard','age','work_age','literacy','phone','email']
|
||||
search_fields = ['code','name','idcard','pinyin']
|
||||
fieldsets = [
|
||||
(None,{'fields':[('code','phone',),('name','pinyin',),('gender','birthday',),('idcard','country',),
|
||||
('position',),('rank','category'),('status','ygxs',),('workday','startday',)]}),
|
||||
(_('other info'),{'fields':[('hometown','address',),('banknum','bankname',),('email','office',),
|
||||
('emergency','literacy',),('religion','marital',),('party','nation',),('spjob','health',),
|
||||
('major','degree',),('tag1','tag2',),('tag3','tag4',),('user',),],'classes':['collapse']}),
|
||||
]
|
||||
readonly_fields = ['status','ygxs','rank','category']
|
||||
inlines = [FamilyInline,EducationInline,WorkExperienceInline]
|
||||
raw_id_fields = ['user']
|
||||
|
||||
def get_queryset(self, request):
|
||||
if request.user.is_superuser or request.user.has_perm('basedata.view_all_employee'):
|
||||
return super(EmployeeAdmin,self).get_queryset(request)
|
||||
else:
|
||||
return super(EmployeeAdmin,self).get_queryset(request).filter(user=request.user)
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if request.user.is_superuser:
|
||||
return []
|
||||
else:
|
||||
return ['status','ygxs','rank','category','position','user']
|
||||
|
||||
|
||||
class DataImportAdmin(generic.BOAdmin):
|
||||
list_display = ['imp_date','title','status']
|
||||
list_display_links = ['imp_date','title']
|
||||
raw_id_fields = ['content_type']
|
||||
readonly_fields = ['status']
|
||||
extra_buttons = [{'href':'action','title':_('import')}]
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
if object_id:
|
||||
obj = DataImport.objects.get(id=object_id)
|
||||
if obj.status == '1':
|
||||
extra_context = extra_context or {}
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(DataImportAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
class DocumentForm(models.ModelForm):
|
||||
title = fields.CharField(widget=TextInput(attrs={"size":"119"}),label=_("title"))
|
||||
keywords = fields.CharField(widget=TextInput(attrs={"size":"119"}),label=_("keywords"))
|
||||
|
||||
class Meta:
|
||||
model = Document
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class DocumentAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'FD'
|
||||
CODE_NUMBER_WIDTH = 4
|
||||
list_display = ['code','title','keywords','tp','business_domain','status','creation']
|
||||
list_display_links = ['code','title']
|
||||
fields = (('code','status',),('title',),('keywords',),('description',),('business_domain','tp',),('attach',))
|
||||
readonly_fields = ['status']
|
||||
list_filter = ['tp','business_domain']
|
||||
search_fields = ['title','keywords','code']
|
||||
form = DocumentForm
|
||||
actions = ['publish']
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj and obj.status=='1':
|
||||
return ['code','status','title','keywords','description','business_domain','tp','attach',]
|
||||
else:
|
||||
return ['status']
|
||||
|
||||
def publish(self,request,queryset):
|
||||
import datetime
|
||||
cnt = queryset.filter(status='0').update(status='1',pub_date=datetime.datetime.now())
|
||||
self.message_user(request,u'%s 个文档发布成功'%cnt)
|
||||
|
||||
publish.short_description = _('publish selected %(verbose_name_plural)s')
|
||||
|
||||
# admin.site.register(Address,AddressAdmin)
|
||||
admin.site.register(ValueList,ValueListAdmin)
|
||||
admin.site.register(Partner,PartnerAdmin)
|
||||
admin.site.register(Project,ProjectAdmin)
|
||||
admin.site.register(Material,MaterialAdmin)
|
||||
admin.site.register(Warehouse,WarehouseAdmin)
|
||||
admin.site.register(Brand,BrandAdmin)
|
||||
admin.site.register(Measure,MeasureAdmin)
|
||||
admin.site.register(Category,CategoryAdmin)
|
||||
admin.site.register(TechnicalParameterName,TechParamNameAdmin)
|
||||
admin.site.register(Trade,TradeAdmin)
|
||||
admin.site.register(ExpenseAccount,ExpenseAdmin)
|
||||
admin.site.register(Employee,EmployeeAdmin)
|
||||
admin.site.register(DataImport,DataImportAdmin)
|
||||
admin.site.register(Document,DocumentAdmin)
|
||||
@@ -0,0 +1,9 @@
|
||||
__author__ = 'zhugl'
|
||||
# created at 15-4-22
|
||||
from django.apps.config import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class BaseDataConfig(AppConfig):
|
||||
name = 'basedata'
|
||||
verbose_name = _('BaseData')
|
||||
@@ -0,0 +1,657 @@
|
||||
# coding=utf-8
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.text import force_text
|
||||
from common import const
|
||||
from common import generic
|
||||
from syscfg.models import Module,Site
|
||||
from organ.models import Organization,Position
|
||||
import datetime
|
||||
from plugin.xls import ExcelManager
|
||||
|
||||
|
||||
class ValueList(generic.BO):
|
||||
"""
|
||||
值列表
|
||||
"""
|
||||
index_weight = 9
|
||||
code = models.CharField(_("list code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("list name"),max_length=const.DB_CHAR_NAME_40)
|
||||
module = models.ForeignKey(Module,verbose_name=_("module"),blank=True,null=True)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
init = models.BooleanField(_("is init"),default=False)
|
||||
locked = models.BooleanField(_("is locked"),default=False)
|
||||
locked_by = models.ForeignKey(User,verbose_name=_("locked by"),blank=True,null=True)
|
||||
lock_time = models.DateTimeField(_("locked time"),null=True,blank=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(ValueList,self).save(force_insert,force_update,using,update_fields)
|
||||
sql = 'update basedata_valuelistitem set group_code = %s where groud_id=%s'
|
||||
params = [self.code,self.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('value list')
|
||||
verbose_name_plural = _('value list')
|
||||
|
||||
|
||||
class ValueListItem(models.Model):
|
||||
"""
|
||||
值列表项
|
||||
"""
|
||||
group = models.ForeignKey(ValueList,verbose_name=_("list group"))
|
||||
group_code = models.CharField(max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
code = models.CharField(_("item code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("item name"),max_length=const.DB_CHAR_NAME_40)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
weight = models.IntegerField(_("weight"),null=True,default=9)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if not self.code:
|
||||
cnt = self.group.valuelistitem_set.count()+1
|
||||
self.code = "%02d" % cnt
|
||||
self.group_code = self.group.code
|
||||
super(ValueListItem,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s-%s" % (self.code,self.name)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('list item')
|
||||
verbose_name_plural = _('list item')
|
||||
ordering = ['weight','code']
|
||||
index_together = ['group','group_code']
|
||||
|
||||
|
||||
def get_value_list(group):
|
||||
"""
|
||||
|
||||
:param group:
|
||||
:return:
|
||||
"""
|
||||
if group:
|
||||
return tuple([(item.code, item.name) for item in ValueListItem.objects.filter(group_code__exact=group,status=1)])
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class Address(generic.BO):
|
||||
"""
|
||||
地址
|
||||
"""
|
||||
ADDRESS_TYPE = get_value_list('S011')
|
||||
address_type = models.CharField(_("address type"),max_length=const.DB_CHAR_CODE_2,choices=ADDRESS_TYPE,default='01')
|
||||
address = models.CharField(_("address"),max_length=const.DB_CHAR_NAME_120)
|
||||
zipcode = models.CharField(_("zipcode"),max_length=const.DB_CHAR_CODE_8,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
contacts = models.CharField(_("contacts"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
|
||||
content_type = models.ForeignKey(ContentType,blank=True,null=True)
|
||||
object_id = models.PositiveIntegerField(blank=True,null=True)
|
||||
content_object = GenericForeignKey('content_type', 'object_id')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('address')
|
||||
verbose_name_plural = _('address')
|
||||
|
||||
|
||||
class Partner(generic.BO):
|
||||
"""
|
||||
合作伙伴
|
||||
"""
|
||||
index_weight = 3
|
||||
PARTNER_TYPE = (
|
||||
('C', _('Customer')),
|
||||
('S', _('Supplier')),
|
||||
)
|
||||
|
||||
LEVEL = (
|
||||
('A','A'),
|
||||
('B','B'),
|
||||
('C','C'),
|
||||
('D','D'),
|
||||
)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
code = models.CharField(_("partner code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
name = models.CharField(_("partner name"),max_length=const.DB_CHAR_NAME_120)
|
||||
short = models.CharField(_("short name"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
partner_type = models.CharField(_("type"),max_length=const.DB_CHAR_CODE_2,choices=PARTNER_TYPE,default='C')
|
||||
level = models.CharField(_("level"),max_length=const.DB_CHAR_CODE_2,choices=LEVEL,default='C')
|
||||
|
||||
tax_num = models.CharField(_("tax num"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
tax_address = models.CharField(_("tax address"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
tax_account = models.CharField(_("tax account"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
|
||||
contacts = models.CharField(_("contacts"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
memo = models.TextField(_("memo"),blank=True,null=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('partner')
|
||||
verbose_name_plural = _('partner')
|
||||
permissions = (
|
||||
('view_all_customer',_("view all customer")),
|
||||
('view_all_supplier',_("view all supplier")),
|
||||
)
|
||||
|
||||
|
||||
class BankAccount(generic.BO):
|
||||
"""
|
||||
银行账户 organization
|
||||
"""
|
||||
account = models.CharField(_("account num"),max_length=const.DB_CHAR_NAME_40)
|
||||
title = models.CharField(_("bank name"),max_length=const.DB_CHAR_NAME_40)
|
||||
memo = models.CharField(_("memo"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
name = ''
|
||||
if self.org:
|
||||
name = self.org.name
|
||||
elif self.partner:
|
||||
name = self.partner.name
|
||||
return u"%s %s %s" % (name,self.account,self.title)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('bank account')
|
||||
verbose_name_plural = _('bank account')
|
||||
|
||||
|
||||
class Project(generic.BO):
|
||||
"""
|
||||
工程项目
|
||||
"""
|
||||
STATUS = get_value_list('S012')
|
||||
TYPES = get_value_list('S013')
|
||||
index_weight = 1
|
||||
|
||||
code = models.CharField(_("project code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
name = models.CharField(_("project name"),max_length=const.DB_CHAR_NAME_120)
|
||||
short = models.CharField(_("short name"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
|
||||
partner = models.ForeignKey(Partner,blank=True,null=True,verbose_name=_("partner"),limit_choices_to={"partner_type":"C"})
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,default='00',choices=STATUS)
|
||||
prj_type = models.CharField(_("project type"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=TYPES,default='00')
|
||||
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
|
||||
budget = models.DecimalField(_("budget"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
income = models.DecimalField(_("income"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
expand = models.DecimalField(_("expand"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
|
||||
blueprint = models.FileField(_("blueprint"),upload_to='project',blank=True,null=True)
|
||||
offer = models.FileField(_("offer sheet"),upload_to='offer sheet',blank=True,null=True)
|
||||
business = models.FileField(_("business document"),upload_to='project',blank=True,null=True)
|
||||
|
||||
users = models.ManyToManyField(User,verbose_name=_("related users"),blank=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('project')
|
||||
verbose_name_plural = _('project')
|
||||
|
||||
|
||||
class Warehouse(models.Model):
|
||||
"""
|
||||
仓库
|
||||
"""
|
||||
index_weight = 6
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_40)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
location = models.CharField(_("location"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
users = models.ManyToManyField(User,verbose_name=_("related users"),blank=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('warehouse')
|
||||
verbose_name_plural = _('warehouse')
|
||||
|
||||
|
||||
class Measure(models.Model):
|
||||
"""
|
||||
计量单位
|
||||
"""
|
||||
index_weight = 5
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_20)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('measure')
|
||||
verbose_name_plural = _('measure')
|
||||
|
||||
|
||||
class Trade(models.Model):
|
||||
"""
|
||||
国民经济行业分类
|
||||
"""
|
||||
index_weight = 102
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_6)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_120)
|
||||
memo = models.CharField(_("memo"),max_length=const.DB_CHAR_NAME_120,null=True,blank=True)
|
||||
parent = models.ForeignKey('self',verbose_name=_("parent"),null=True,blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('trade')
|
||||
verbose_name_plural = _('trade')
|
||||
ordering = ['code']
|
||||
|
||||
|
||||
class Brand(models.Model):
|
||||
"""
|
||||
品牌
|
||||
"""
|
||||
index_weight = 101
|
||||
trade = models.ForeignKey(Trade,verbose_name=_("trade"),null=True,blank=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_120)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
weight = models.IntegerField(_("weight"),blank=True,null=True,default=99)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('brand')
|
||||
verbose_name_plural = _('brand')
|
||||
|
||||
|
||||
class Category(models.Model):
|
||||
"""
|
||||
分类
|
||||
"""
|
||||
index_weight = 100
|
||||
trade = models.ForeignKey(Trade,verbose_name=_("trade"),null=True,blank=True)
|
||||
parent = models.ForeignKey('self',verbose_name=_("parent"),null=True,blank=True)
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_6,null=True,blank=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_120)
|
||||
path = models.CharField(_("path"),max_length=const.DB_CHAR_NAME_200,null=True,blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('category')
|
||||
verbose_name_plural = _('category')
|
||||
|
||||
|
||||
class TechnicalParameterName(models.Model):
|
||||
"""
|
||||
技术参数-名称,将技术参数绑定于物料分类上,在此分类下的物料自动继承全部技术参数
|
||||
"""
|
||||
index_weight = 7
|
||||
category = models.ForeignKey(Category,verbose_name=_("material category"))
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_40)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('technical parameter')
|
||||
verbose_name_plural = _('technical parameter')
|
||||
|
||||
|
||||
class TechnicalParameterValue(models.Model):
|
||||
"""
|
||||
技术参数-值,将技术参数绑定于物料分类上,在此分类下的物料自动继承全部技术参数
|
||||
"""
|
||||
tech_name = models.ForeignKey(TechnicalParameterName,verbose_name=_("technical name"))
|
||||
value = models.CharField(_("value"),max_length=const.DB_CHAR_NAME_80)
|
||||
description = models.CharField(_("description"),max_length=const.DB_CHAR_NAME_80,null=True,blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.value
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('technical value')
|
||||
verbose_name_plural = _('technical value')
|
||||
|
||||
|
||||
class Material(generic.BO):
|
||||
"""
|
||||
物料
|
||||
"""
|
||||
index_weight = 4
|
||||
code = models.CharField(_("material code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
barcode = models.CharField(_("bar code"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
name = models.CharField(_("material name"),max_length=const.DB_CHAR_NAME_120)
|
||||
spec = models.CharField(_("specifications"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
brand = models.ForeignKey(Brand,blank=True,null=True,verbose_name=_("brand"))
|
||||
category = models.ForeignKey(Category,blank=True,null=True,verbose_name=_("category"))
|
||||
tp = models.CharField(_('mt type'),blank=True,null=True,max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('S054'),default='10')
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
is_equip = models.BooleanField(_("is equipment"),default=False)
|
||||
can_sale = models.BooleanField(_("can sale"),default=True)
|
||||
is_virtual = models.BooleanField(_("is virtual"),default=False)
|
||||
|
||||
warehouse = models.ForeignKey(Warehouse,blank=True,null=True,verbose_name=_("warehouse"))
|
||||
measure = models.ManyToManyField(Measure,verbose_name=_("measure"))
|
||||
|
||||
params = models.ManyToManyField(TechnicalParameterValue,verbose_name=_("technical parameter"),through='MaterialParam')
|
||||
|
||||
stock_price = models.DecimalField(_("stock price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
purchase_price = models.DecimalField(_("purchase price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
sale_price = models.DecimalField(_("sale price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
|
||||
return "%s %s" % (self.code,self.name)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('material')
|
||||
verbose_name_plural = _('material')
|
||||
ordering = ['tp','code']
|
||||
|
||||
|
||||
class MaterialParam(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
material = models.ForeignKey(Material)
|
||||
param_value = models.ForeignKey(TechnicalParameterValue)
|
||||
param_name = models.ForeignKey(TechnicalParameterName,blank=Trade,null=True)
|
||||
creation = models.DateField(auto_now_add=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.param_value
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('material parameter')
|
||||
verbose_name_plural = _('material parameter')
|
||||
|
||||
|
||||
class ExtraParam(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
DATA_TYPE = (
|
||||
('CHAR',_('CHAR')),
|
||||
('NUM',_('NUMBER')),
|
||||
('DATE',_('DATE')),
|
||||
)
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"))
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_40)
|
||||
data_type = models.CharField(_("data type"),default='CHAR',choices=DATA_TYPE,max_length=const.DB_CHAR_CODE_6)
|
||||
data_source = models.CharField(_("data source"),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s" % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("extra param")
|
||||
verbose_name_plural = _("extra params")
|
||||
|
||||
|
||||
class ExpenseAccount(generic.BO):
|
||||
"""
|
||||
费用科目
|
||||
"""
|
||||
CATEGORY = (
|
||||
('HR',_('HR-DOMAIN')),
|
||||
('OF',_('OFFICE-DOMAIN')),
|
||||
('PU',_('PUBLIS-DOMAIN')),
|
||||
('MU',_('MUNADOMAIN')),
|
||||
('BU',_('BUSINESS')),
|
||||
('OT',_('OTHER')),
|
||||
)
|
||||
index_weight = 10
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_120)
|
||||
category = models.CharField(_("category"),max_length=const.DB_CHAR_CODE_4,choices=CATEGORY,default='PU')
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
parent = models.ForeignKey('self',verbose_name=_("parent"),null=True,blank=True)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('expenses account')
|
||||
verbose_name_plural = _('expenses account')
|
||||
ordering = ['category','code']
|
||||
|
||||
|
||||
class Employee(generic.BO):
|
||||
"""
|
||||
职员信息
|
||||
"""
|
||||
index_weight = 2
|
||||
code = models.CharField(_("employee number"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
organization = models.ForeignKey(Organization,verbose_name = _('organization'),null=True,blank=True)
|
||||
name = models.CharField(_("employee name"),max_length=const.DB_CHAR_NAME_120)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
birthday = models.DateField(_("birthday"),blank=True,null=True)
|
||||
|
||||
gender = models.CharField(_("gender"),max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('gender'),default='1')
|
||||
idcard = models.CharField(_("id card"),max_length=const.DB_CHAR_NAME_20)
|
||||
|
||||
country = models.CharField(_("nationality"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,default='CN',choices=const.get_value_list('S022'))
|
||||
hometown = models.CharField(_("hometown"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
address = models.CharField(_("home address"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
banknum = models.CharField(_("bank account"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
bankname = models.CharField(_("bank name"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
emergency = models.CharField(_("emergency contacts"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
email = models.CharField(_("email"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
office = models.CharField(_("office phone"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
|
||||
position = models.ForeignKey(Position,verbose_name = _('position'))
|
||||
rank = models.CharField(_("employee rank"),max_length=const.DB_CHAR_CODE_2,default='00',choices=const.get_value_list('S017'))
|
||||
|
||||
workday = models.DateField(_("workday"),blank=True,null=True)
|
||||
startday = models.DateField(_("start date"),blank=True,null=True)
|
||||
|
||||
religion = models.CharField(_("religion"),max_length=const.DB_CHAR_CODE_2,default='00',choices=const.get_value_list('S020'),blank=True,null=True,)
|
||||
marital = models.CharField(_("marital status"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S023'),default='10')
|
||||
|
||||
party = models.CharField(_("political party"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S026'),default='13')
|
||||
nation = models.CharField(_("nation"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S021'),default='01')
|
||||
|
||||
ygxs = models.CharField(_("employ ygxs"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S019'),default='2')
|
||||
status = models.CharField(_("employ status"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S016'),default='10')
|
||||
category = models.CharField(_("employ category"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S018'),default='21')
|
||||
|
||||
literacy = models.CharField(_("literacy"),max_length=const.DB_CHAR_CODE_2,default='10',choices=const.get_value_list('S024'),blank=True,null=True)
|
||||
major = models.CharField(_("major type"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S038'),default='99')
|
||||
degree = models.CharField(_("major degree"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S037'),default='4')
|
||||
|
||||
spjob = models.CharField(_("special job"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S042'),default='00')
|
||||
health = models.CharField(_("health"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S043'),default='1')
|
||||
|
||||
tag1 = models.CharField(_("tag1 fzjr"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S039'),default='99')
|
||||
tag2 = models.CharField(_("tag2 dwld"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S040'),default='9')
|
||||
tag3 = models.CharField(_("tag3 dsjs"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S041'),default='00')
|
||||
tag4 = models.CharField(_("tag4 byzk"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S027'),default='0')
|
||||
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
|
||||
def age(self):
|
||||
import datetime
|
||||
if self.birthday:
|
||||
cnt = datetime.date.today().year-self.birthday.year
|
||||
return cnt
|
||||
|
||||
def work_age(self):
|
||||
import datetime
|
||||
if self.birthday and self.workday:
|
||||
cnt = datetime.date.today().year-self.workday.year
|
||||
return cnt
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s'%(self.code,self.name)
|
||||
|
||||
age.short_description = u'年龄'
|
||||
work_age.short_description = u'工龄'
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("employee")
|
||||
verbose_name_plural = _("employee")
|
||||
permissions = (
|
||||
('view_all_employee',_("view all employee")),
|
||||
)
|
||||
|
||||
|
||||
class Family(generic.BO):
|
||||
"""
|
||||
家庭成员
|
||||
"""
|
||||
relation = models.CharField(_("family title"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S025'))
|
||||
status = models.CharField(_("social status"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S029'),default='17')
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_60)
|
||||
birthday = models.DateField(_("birthday"),blank=True,null=True)
|
||||
organization = models.CharField(_("organization"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
emergency = models.BooleanField(_("emergency"),default=False)
|
||||
employee = models.ForeignKey(Employee,verbose_name=_("employee"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("family member")
|
||||
verbose_name_plural = _("family member")
|
||||
|
||||
|
||||
class Education(generic.BO):
|
||||
"""
|
||||
教育履历
|
||||
"""
|
||||
edu_type = models.CharField(_("edu type"),max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('S035'),default='1')
|
||||
school = models.CharField(_("school"),max_length=const.DB_CHAR_NAME_120)
|
||||
major = models.CharField(_("major"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
degree = models.CharField(_("major degree"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S037'),default='4')
|
||||
employee = models.ForeignKey(Employee,verbose_name=_("employee"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("education experience")
|
||||
verbose_name_plural = _("education experience")
|
||||
|
||||
|
||||
class WorkExperience(generic.BO):
|
||||
"""
|
||||
工作履历
|
||||
"""
|
||||
organization = models.CharField(_("organization"),max_length=const.DB_CHAR_NAME_120)
|
||||
position = models.CharField(_("position"),max_length=const.DB_CHAR_NAME_120)
|
||||
employee = models.ForeignKey(Employee,verbose_name=_("employee"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("work experience")
|
||||
verbose_name_plural = _("work experience")
|
||||
|
||||
|
||||
class DataImport(generic.BO):
|
||||
|
||||
"""
|
||||
Data import
|
||||
"""
|
||||
actions = {}
|
||||
|
||||
STATUS = (
|
||||
('0',_('NEW')),
|
||||
('1',_('EXECUTED')),
|
||||
)
|
||||
imp_date = models.DateField(_('date'),blank=True,null=True,default=datetime.datetime.today)
|
||||
title = models.CharField(_('title'),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_('description'),blank=True,null=True)
|
||||
content_type = models.ForeignKey(ContentType,verbose_name=_("content type"),limit_choices_to={"app_label__in":['basedata','organ','auth']})
|
||||
attach = models.FileField(_('attach'),blank=True,null=True,upload_to='data')
|
||||
is_clear = models.BooleanField(_('clear old data?'),default=0)
|
||||
handler = models.CharField(_('handler class'),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
status = models.CharField(_('status'),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
|
||||
def action_import(self,request):
|
||||
from django.db import transaction
|
||||
if self.attach:
|
||||
if self.handler:
|
||||
klass = ExcelManager().handlers.get(self.handler)
|
||||
with transaction.atomic():
|
||||
klass.handle(self,self.attach)
|
||||
self.status = 1
|
||||
self.save()
|
||||
else:
|
||||
import xlrd
|
||||
import os
|
||||
from mis import settings
|
||||
path = os.path.join(settings.MEDIA_ROOT,self.attach.name)
|
||||
workbook = xlrd.open_workbook(path)
|
||||
sheet = workbook.sheet_by_index(0)
|
||||
row_count = sheet.nrows
|
||||
col_count = sheet.ncols
|
||||
cols = []
|
||||
with transaction.atomic():
|
||||
for row_index in range(row_count):
|
||||
line = sheet.row_values(row_index)
|
||||
if row_index == 0:
|
||||
cols = line
|
||||
continue
|
||||
elif row_index == 1:
|
||||
continue
|
||||
else:
|
||||
klass = self.content_type.model_class()
|
||||
values = line
|
||||
params = {}
|
||||
for name in cols:
|
||||
index = cols.index(name)
|
||||
v = values[index]
|
||||
if type(v) == str:
|
||||
v = force_text(v.decode('gbk'))
|
||||
params[name]=v
|
||||
# print 'name is %s value is %s'%(name,v)
|
||||
try:
|
||||
params.pop('')
|
||||
except Exception,e:
|
||||
pass
|
||||
# print params
|
||||
klass.objects.create(**params)
|
||||
self.status = '1'
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("data import")
|
||||
verbose_name_plural = _("data import")
|
||||
|
||||
|
||||
class Document(generic.BO):
|
||||
"""
|
||||
文档管理
|
||||
"""
|
||||
TP = (
|
||||
('00',_('SYSTEM MANUAL')),
|
||||
('10',_('BUSINESS DOC')),
|
||||
)
|
||||
STATUS = (
|
||||
('0',_('draft')),
|
||||
('1',_('published'))
|
||||
)
|
||||
index_weight = 8
|
||||
code = models.CharField(_('code'),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
title = models.CharField(_('title'),max_length=const.DB_CHAR_NAME_120)
|
||||
keywords = models.CharField(_('keywords'),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
description = models.TextField(_('description'),blank=True,null=True)
|
||||
tp = models.CharField(_('type'),max_length=const.DB_CHAR_CODE_2,default='10',choices=TP)
|
||||
business_domain = models.CharField(_("business domain"),max_length=const.DB_CHAR_CODE_4,choices=const.get_value_list('S045'),default='OT')
|
||||
user = models.ForeignKey(User,verbose_name=_('user'),blank=True,null=True)
|
||||
status = models.CharField(_('status'),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
pub_date = models.DateTimeField(_('publish date'),blank=True,null=True)
|
||||
size = models.CharField(_('size'),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
attach = models.FileField(_('attach'),blank=True,null=True,upload_to='doc')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("document")
|
||||
verbose_name_plural = _("documents")
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.conf.urls import include, url,static
|
||||
import basedata.views
|
||||
|
||||
urlpatterns = [
|
||||
url(r"dataimport/(?P<object_id>\d+)/action", 'basedata.views.action_import'),
|
||||
]
|
||||
@@ -0,0 +1,42 @@
|
||||
# coding=utf-8
|
||||
from django.contrib.admin import site
|
||||
from django.http.response import HttpResponseRedirect
|
||||
from django.utils.encoding import force_text
|
||||
from django.template.response import TemplateResponse
|
||||
from django.contrib import messages
|
||||
from basedata.models import DataImport
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
def action_import(request,object_id):
|
||||
"""
|
||||
数据导入操作
|
||||
:param request:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
title = _("Are you sure?")
|
||||
obj = DataImport.objects.get(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if request.POST.get("post"):
|
||||
obj.action_import(request)
|
||||
try:
|
||||
|
||||
messages.success(request,_('data import successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
|
||||
return HttpResponseRedirect("/admin/basedata/dataimport/%s"%(object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockin/in_confirmation.html', context)
|
||||
@@ -0,0 +1 @@
|
||||
__author__ = 'Administrator'
|
||||
@@ -0,0 +1,39 @@
|
||||
# coding=utf-8
|
||||
from django.db import connection
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
__author__ = 'zhugl'
|
||||
|
||||
DB_CHAR_CODE_2 = 2
|
||||
DB_CHAR_CODE_4 = 4
|
||||
DB_CHAR_CODE_6 = 6
|
||||
DB_CHAR_CODE_8 = 8
|
||||
DB_CHAR_CODE_10 = 10
|
||||
|
||||
DB_CHAR_NAME_20 = 20
|
||||
DB_CHAR_NAME_40 = 40
|
||||
DB_CHAR_NAME_60 = 60
|
||||
DB_CHAR_NAME_80 = 80
|
||||
DB_CHAR_NAME_120 = 120
|
||||
DB_CHAR_NAME_200 = 200
|
||||
|
||||
|
||||
STATUS_ON_OFF = (
|
||||
(0,_('OFF')),
|
||||
(0,_('ON')),
|
||||
)
|
||||
|
||||
|
||||
def get_value_list(group):
|
||||
"""
|
||||
获取值列表信息
|
||||
"""
|
||||
if group:
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.execute('SELECT code,name FROM basedata_valuelistitem WHERE group_code=%s AND status=1',[group])
|
||||
rows = cursor.fetchall()
|
||||
return tuple([(code,name) for code,name in rows])
|
||||
except Exception,e:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
@@ -0,0 +1,312 @@
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
# created at 15-4-21
|
||||
import datetime
|
||||
import xlwt
|
||||
import re
|
||||
from django.db import models
|
||||
from django.db import connection,transaction
|
||||
from django.db.models import fields
|
||||
from django.db.models.fields import related
|
||||
from django.contrib import admin
|
||||
from django.http import HttpRequest,HttpResponseRedirect,HttpResponse
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.text import force_text
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.http import urlquote
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import const
|
||||
from midware import cuser
|
||||
|
||||
|
||||
def update(sql, params=None):
|
||||
"""
|
||||
:param sql:
|
||||
:param params:
|
||||
:return:
|
||||
"""
|
||||
cursor = connection.cursor()
|
||||
with transaction.atomic():
|
||||
try:
|
||||
if params:
|
||||
cursor.execute(sql,params)
|
||||
else:
|
||||
cursor.execute(sql)
|
||||
except Exception,e:
|
||||
print e
|
||||
|
||||
def get_app_model_info_from_request(request):
|
||||
"""
|
||||
|
||||
"""
|
||||
if request and isinstance(request,HttpRequest):
|
||||
import re
|
||||
pattern = re.compile(r"/(admin)/(\w+)/(\w+)/(\d+)")
|
||||
match = pattern.match(request.path)
|
||||
|
||||
if match and match.group():
|
||||
app = match.group(2)
|
||||
model = match.group(3)
|
||||
oid = match.group(4)
|
||||
ct = ContentType.objects.get(app_label=app,model=model)
|
||||
obj = ct.get_object_for_this_type(id=oid)
|
||||
return {'app':app,'model':model,'id':oid,'obj':obj}
|
||||
return None
|
||||
|
||||
|
||||
class MineBOManager(models.Manager):
|
||||
"""
|
||||
get the objects created by current login user
|
||||
"""
|
||||
def get_query_set(self):
|
||||
return super(MineBOManager,self).get_query_set().filter(creator=cuser.getuser())
|
||||
|
||||
|
||||
class BOManager(models.Manager):
|
||||
"""
|
||||
"""
|
||||
def get_query_set(self):
|
||||
return super(BOManager,self).get_query_set()
|
||||
|
||||
|
||||
class BO(models.Model):
|
||||
"""
|
||||
All business object derive from this class
|
||||
"""
|
||||
begin = models.DateField(_('begin date'),blank=True,null=True)
|
||||
end = models.DateField(_('end date'),blank=True,null=True)
|
||||
creator = models.CharField(_("creator"),blank=True,null=True,max_length=const.DB_CHAR_NAME_20)
|
||||
modifier = models.CharField(_("modifier"),blank=True,null=True,max_length=const.DB_CHAR_NAME_20)
|
||||
creation = models.DateTimeField(_('creation'),auto_now_add=True,blank=True,null=True)
|
||||
modification = models.DateTimeField(_('modification'),auto_now=True,blank=True,null=True)
|
||||
# mine = MineBOManager()
|
||||
objects = models.Manager()
|
||||
|
||||
def __unicode__(self):
|
||||
display = getattr(self,'name',None) or getattr(self,'title',None) or getattr(self,'description',None)
|
||||
if not display:
|
||||
display = ' '
|
||||
return u'%s' % display
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class BOAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
All business object admin derive from this class
|
||||
"""
|
||||
CODE_NUMBER_WIDTH = 4
|
||||
CODE_PREFIX = '9'
|
||||
extra_buttons = []
|
||||
|
||||
exclude = ['creator','modifier','creation','modification','begin','end']
|
||||
list_per_page = 18
|
||||
actions = ['export_selected_data']
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param object_id:
|
||||
:param form_url:
|
||||
:param extra_context:
|
||||
:return:
|
||||
"""
|
||||
app_info = get_app_model_info_from_request(request)
|
||||
workflow_modal = None
|
||||
workflow_instance = None
|
||||
has_workflow_modal = False
|
||||
has_workflow_instance = False
|
||||
show_workflow_line = False
|
||||
show_submit_button = False
|
||||
can_restart = False
|
||||
can_edit = False
|
||||
# print app_info
|
||||
if app_info:
|
||||
try:
|
||||
modal = ContentType.objects.get(app_label='workflow',model='modal')
|
||||
workflow_modal = modal.get_object_for_this_type(app_name=app_info['app'],model_name=app_info['model'])
|
||||
has_workflow_modal = True
|
||||
# print workflow_modal.code
|
||||
instance = ContentType.objects.get(app_label='workflow',model='instance')
|
||||
workflow_instance = instance.get_object_for_this_type(modal=workflow_modal,object_id=app_info['id'])
|
||||
has_workflow_instance = True
|
||||
todo = ContentType.objects.get(app_label='workflow',model='todolist')
|
||||
todo_list = todo.model_class().objects.filter(inst=workflow_instance,status=0,user=request.user)
|
||||
x = todo_list.all()
|
||||
|
||||
if x and len(x)>0:
|
||||
can_edit = x[0].node.can_edit
|
||||
if todo_list.count() > 0:
|
||||
# print 'we fount it'
|
||||
unread = todo_list.filter(is_read=0)
|
||||
show_workflow_line = True
|
||||
if unread.count() > 0:
|
||||
unread.update(is_read=1,read_time=datetime.datetime.now())
|
||||
if workflow_instance.status == 3 and request.user == workflow_instance.starter:
|
||||
can_restart = True
|
||||
show_workflow_line = True
|
||||
|
||||
except Exception,e:
|
||||
print Exception,e
|
||||
|
||||
if workflow_modal and not workflow_instance:
|
||||
show_submit_button = True
|
||||
extra_context = extra_context or {}
|
||||
ctx = dict(
|
||||
has_workflow_instance = has_workflow_instance,
|
||||
has_workflow_modal = has_workflow_modal,
|
||||
workflow_modal = workflow_modal,
|
||||
workflow_instance = workflow_instance,
|
||||
show_workflow_line = show_workflow_line,
|
||||
can_restart = can_restart,
|
||||
can_edit = can_edit,
|
||||
show_submit_button = show_submit_button,
|
||||
)
|
||||
if len(self.extra_buttons) > 0:
|
||||
buttons = dict(
|
||||
extra_buttons = self.extra_buttons
|
||||
)
|
||||
ctx.update(buttons)
|
||||
extra_context.update(ctx)
|
||||
# print extra_context
|
||||
return super(BOAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
def history_view(self, request, object_id, extra_context=None):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param object_id:
|
||||
:param extra_context:
|
||||
:return:
|
||||
"""
|
||||
app_info = get_app_model_info_from_request(request)
|
||||
# print app_info
|
||||
if app_info:
|
||||
try:
|
||||
modal = ContentType.objects.get(app_label='workflow',model='modal')
|
||||
workflow_modal = modal.get_object_for_this_type(app_name=app_info['app'],model_name=app_info['model'])
|
||||
has_workflow_modal = True
|
||||
instance = ContentType.objects.get(app_label='workflow',model='instance')
|
||||
workflow_instance = instance.get_object_for_this_type(modal=workflow_modal,object_id=app_info['id'])
|
||||
has_workflow_instance = True
|
||||
history = ContentType.objects.get(app_label='workflow',model='history')
|
||||
history_list = history.model_class().objects.filter(inst=workflow_instance)
|
||||
has_history = True
|
||||
todo = ContentType.objects.get(app_label='workflow',model='todolist')
|
||||
todo_list = todo.model_class().objects.filter(inst=workflow_instance,status=0).exclude(node=None)
|
||||
|
||||
extra_context = extra_context or {}
|
||||
ctx = dict(
|
||||
has_workflow_instance = has_workflow_instance,
|
||||
has_workflow_modal = has_workflow_modal,
|
||||
workflow_modal = workflow_modal,
|
||||
workflow_instance = workflow_instance,
|
||||
history_list = history_list,
|
||||
has_history = has_history,
|
||||
todo_list = todo_list,
|
||||
)
|
||||
# print history_list
|
||||
extra_context.update(ctx)
|
||||
except Exception,e:
|
||||
print Exception,e
|
||||
pass
|
||||
return super(BOAdmin,self).history_view(request,object_id,extra_context)
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
import datetime
|
||||
return {'begin':datetime.date.today,'end':datetime.date(9999,12,31)}
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
|
||||
if change:
|
||||
setattr(obj,'modifier',request.user.username)
|
||||
else:
|
||||
setattr(obj,'creator',request.user.username)
|
||||
setattr(obj,'begin',datetime.date.today())
|
||||
setattr(obj,'end',datetime.date(9999,12,31))
|
||||
try:
|
||||
setattr(obj,'user',request.user)
|
||||
except Exception,e:
|
||||
pass
|
||||
|
||||
super(BOAdmin,self).save_model(request,obj,form,change)
|
||||
# print '=========it is here========='
|
||||
try:
|
||||
code = getattr(obj,'code')
|
||||
# print code
|
||||
if code is None or len(code) == 0:
|
||||
fmt = '%s%0'+str(self.CODE_NUMBER_WIDTH)+'d'
|
||||
code = fmt % (self.CODE_PREFIX,obj.id)
|
||||
table = obj._meta.db_table
|
||||
sql = 'update %s set code = \'%s\' where id=%s' % (table,code,obj.id)
|
||||
print sql
|
||||
update(sql)
|
||||
except Exception,e:
|
||||
print e
|
||||
|
||||
# def response_change(self, request, obj):
|
||||
# return HttpResponseRedirect('')
|
||||
|
||||
def export_selected_data(self,request,queryset):
|
||||
ops = self.model._meta
|
||||
workbook = xlwt.Workbook(encoding='utf-8')
|
||||
dd = datetime.date.today().strftime('%Y%m%d')
|
||||
file_name = force_text(ops.verbose_name+dd)
|
||||
sheet = workbook.add_sheet(force_text(ops.verbose_name))
|
||||
obj_fields = getattr(self,'export_fields',None) or self.list_display or self.fields
|
||||
|
||||
head_col_index = 0
|
||||
for field in obj_fields:
|
||||
col_name = field
|
||||
try:
|
||||
f = ops.get_field(field)
|
||||
col_name = f.verbose_name
|
||||
except Exception,e:
|
||||
f = getattr(self.model,field)
|
||||
if hasattr(f,'short_description'):
|
||||
col_name = f.short_description
|
||||
sheet.write(0,head_col_index,force_text(col_name))
|
||||
head_col_index+=1
|
||||
row_index = 1
|
||||
for obj in queryset:
|
||||
col_index = 0
|
||||
for field in obj_fields:
|
||||
f = field
|
||||
try:
|
||||
f = ops.get_field(field)
|
||||
except Exception,e:
|
||||
pass
|
||||
v = getattr(obj,field,'')
|
||||
if hasattr(v,'__call__') or callable(v):
|
||||
v = v()
|
||||
elif type(f) == fields.DateField:
|
||||
v = v.strftime('%Y-%m-%d')
|
||||
elif type(f) == fields.DateTimeField:
|
||||
v = v.strftime('%Y-%m-%d %H:%M')
|
||||
elif type(f) == fields.CharField and f.choices:
|
||||
fc = 'get_'+field+'_display'
|
||||
v = getattr(obj,fc)()
|
||||
elif type(f) == related.ForeignKey:
|
||||
v = str(v)
|
||||
sheet.write(row_index,col_index,v)
|
||||
col_index += 1
|
||||
row_index += 1
|
||||
response = HttpResponse(content_type='application/vnd.ms-excel')
|
||||
agent = request.META.get('HTTP_USER_AGENT')
|
||||
nn = smart_str(file_name)
|
||||
if agent and re.search('MSIE',agent):
|
||||
nn = urlquote(file_name)
|
||||
response['Content-Disposition'] = 'attachment; filename=%s.xls'%nn
|
||||
workbook.save(response)
|
||||
return response
|
||||
#self.message_user(request,'SUCCESS')
|
||||
export_selected_data.short_description = _("export selected %(verbose_name_plural)s")
|
||||
|
||||
class Meta:
|
||||
ordering = ['-creation']
|
||||
|
||||
class Media:
|
||||
css = {'all':('css/maximus.css',)}
|
||||
js = ('js/maximus.js',)
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = 'hr.apps.MyAppConfig'
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# coding = utf-8
|
||||
from django.contrib import admin
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from common import const
|
||||
from hr.models import Entry,SalaryItem,EmployeeSalaryItem
|
||||
|
||||
|
||||
class SalaryItemAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','classification','name','plus_or_minus','required']
|
||||
list_display_links = ['code','name']
|
||||
list_per_page = 20
|
||||
|
||||
|
||||
class EmployeeSalaryItemInline(admin.TabularInline):
|
||||
model = EmployeeSalaryItem
|
||||
exclude = ['employee']
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'salary_item':
|
||||
kwargs['queryset'] = SalaryItem.objects.filter(required=1)
|
||||
|
||||
return super(EmployeeSalaryItemInline,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
class EntryAdmin(generic.BOAdmin):
|
||||
list_display = ['code','name','gender','position','rank','probation_months','probation_end']
|
||||
inlines = [EmployeeSalaryItemInline]
|
||||
fieldsets = [
|
||||
(None,{'fields':[('code','position',),('name','pinyin',),('address','zipcode',),('idcard','phone',),('memo',),('profile',)]}),
|
||||
(_('org distribute'),{'fields':[('guider',),('rank','ygxs',),('category','probation_months',),('probation_begin','probation_end',)],'classes': ['collapse']})
|
||||
]
|
||||
raw_id_fields = ['position','guider']
|
||||
def get_changeform_initial_data(self, request):
|
||||
import datetime
|
||||
end = datetime.date.today()+datetime.timedelta(90)
|
||||
return {'probation_end':end}
|
||||
|
||||
|
||||
admin.site.register(SalaryItem,SalaryItemAdmin)
|
||||
admin.site.register(Entry,EntryAdmin)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
# created at 15-5-23
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class MyAppConfig(AppConfig):
|
||||
name = 'hr'
|
||||
verbose_name = _("human resource")
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
# coding=utf-8
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from common import const
|
||||
from basedata.models import Position,Employee
|
||||
from organ.models import OrgUnit
|
||||
import datetime
|
||||
|
||||
|
||||
class SalaryItemHandler:
|
||||
code = None
|
||||
|
||||
def __init__(self,employee):
|
||||
self.employee = employee
|
||||
|
||||
def value(self):
|
||||
return 0
|
||||
|
||||
|
||||
class SalaryItem(models.Model):
|
||||
"""
|
||||
工资项
|
||||
"""
|
||||
formulas = {}
|
||||
|
||||
@classmethod
|
||||
def add_formula(cls, code, handler):
|
||||
SalaryItem.formulas[code] = handler
|
||||
|
||||
@classmethod
|
||||
def get_formula(cls):
|
||||
return SalaryItem.formulas.get(cls.code,None)
|
||||
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_10,null=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_120)
|
||||
classification = models.CharField(_("classification"),max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('S048'),default='10')
|
||||
plus_or_minus = models.CharField(_("plus or minus"),max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('S049'),default='+')
|
||||
required = models.BooleanField(_("is required"),default=0)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s %s" % (self.code,self.name)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('salary item')
|
||||
verbose_name_plural = _('salary items')
|
||||
ordering = ('code',)
|
||||
|
||||
|
||||
class Entry(generic.BO):
|
||||
"""
|
||||
人员入职
|
||||
"""
|
||||
code = models.CharField(_("employee number"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
name = models.CharField(_("employee name"),max_length=const.DB_CHAR_NAME_120)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
birthday = models.DateField(_("birthday"),blank=True,null=True)
|
||||
gender = models.CharField(_("gender"),max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('gender'),default='1')
|
||||
idcard = models.CharField(_("id card"),max_length=const.DB_CHAR_NAME_20)
|
||||
address = models.CharField(_("mail address"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
zipcode = models.CharField(_("zipcode"),max_length=const.DB_CHAR_CODE_8)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
|
||||
guider = models.ForeignKey(Employee,verbose_name=_("guider"))
|
||||
position = models.ForeignKey(Position,verbose_name = _('designate position'))
|
||||
rank = models.CharField(_("employee rank"),max_length=const.DB_CHAR_CODE_2,default='00',choices=const.get_value_list('S017'))
|
||||
ygxs = models.CharField(_("employ ygxs"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S019'),default='2')
|
||||
category = models.CharField(_("employ category"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=const.get_value_list('S018'),default='21')
|
||||
|
||||
probation_months = models.CharField(_("probation months"),max_length=2,default='3',choices=const.get_value_list('S047'))
|
||||
probation_begin = models.DateField(_("probation begin"),default=datetime.date.today)
|
||||
probation_end = models.DateField(_("probation end"),blank=True,null=True)
|
||||
|
||||
memo = models.TextField(_("memo"),blank=True,null=True)
|
||||
profile = models.FileField(_("profile"),blank=True,null=True,upload_to='hr profile')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("employee entry")
|
||||
verbose_name_plural = _("employee entries")
|
||||
permissions = (
|
||||
('modify_salary_item',_("modify salary item")),
|
||||
)
|
||||
|
||||
|
||||
class EmployeeSalaryItem(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
entry = models.ForeignKey(Entry,verbose_name=_("employee entry"))
|
||||
employee = models.ForeignKey(Employee,verbose_name=_("employee"),blank=True,null=True)
|
||||
salary_item = models.ForeignKey(SalaryItem,verbose_name=_("salary item"))
|
||||
calculate_way = models.CharField(_("calculate way"),max_length=const.DB_CHAR_CODE_2,choices=const.get_value_list('S050'),default='10')
|
||||
fixed_value = models.DecimalField(_("fixed value"),blank=True,null=True,max_digits=10,decimal_places=2)
|
||||
base_value = models.DecimalField(_("base value"),blank=True,null=True,max_digits=10,decimal_places=2)
|
||||
org_percent = models.DecimalField(_("org percent"),blank=True,null=True,max_digits=4,decimal_places=2)
|
||||
employee_percent = models.DecimalField(_("employee percent"),blank=True,null=True,max_digits=4,decimal_places=2)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("salary item")
|
||||
verbose_name_plural = _("salary item")
|
||||
unique_together = (('entry', 'salary_item'),)
|
||||
|
||||
|
||||
class Transfer(generic.BO):
|
||||
"""
|
||||
人员调动
|
||||
"""
|
||||
employee = models.ForeignKey(Employee,verbose_name=_("employee"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("employee transfer")
|
||||
verbose_name_plural = _("employee transfers")
|
||||
|
||||
|
||||
class Departure(generic.BO):
|
||||
"""
|
||||
人员离职
|
||||
"""
|
||||
employee = models.ForeignKey(Employee,verbose_name=_("employee"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("employee departure")
|
||||
verbose_name_plural = _("employee departures")
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "invent.apps.MyAppConfig"
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from basedata.models import Material
|
||||
from invent.models import StockIn,StockOut,InitialInventory,InItem,OutItem,InitItem,Inventory,InItemForm,InOutDetail,\
|
||||
WareReturn,ReturnItem,WareAdjust,AdjustItem
|
||||
|
||||
|
||||
class InItemInline(admin.TabularInline):
|
||||
model = InItem
|
||||
form = InItemForm
|
||||
fields = ('material', 'measure', 'cnt', 'price')
|
||||
raw_id_fields = ['material']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj and obj.status == 1:
|
||||
return ['material', 'measure', 'cnt', 'price']
|
||||
else:
|
||||
return []
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'material':
|
||||
kwargs['queryset'] = Material.objects.filter(is_virtual=0)
|
||||
return super(InItemInline,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
|
||||
class OutItemInline(admin.TabularInline):
|
||||
model = OutItem
|
||||
fields = ('inventory', 'measure', 'cnt', 'price','warehouse',)
|
||||
raw_id_fields = ['inventory']
|
||||
readonly_fields = ['measure', 'price', 'warehouse']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
class InitItemInline(admin.TabularInline):
|
||||
model = InitItem
|
||||
fields = ('material', 'measure', 'cnt', 'warehouse', 'price',)
|
||||
raw_id_fields = ['material']
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj and obj.execute_time:
|
||||
return ['material', 'measure', 'cnt', 'warehouse', 'price']
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'material':
|
||||
kwargs['queryset'] = Material.objects.filter(is_virtual=0)
|
||||
return super(InitItemInline,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
|
||||
class StockInAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'RK'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','title','money_of_amount','status','entry_time']
|
||||
inlines = [InItemInline]
|
||||
raw_id_fields = ['po']
|
||||
fields = (
|
||||
('code',),('title',),('po',),('warehouse',),('batch',),('status','amount',)
|
||||
)
|
||||
date_hierarchy = 'begin'
|
||||
extra_buttons = [{'href':'cin','title':_('Action Stock In')}]
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
import decimal
|
||||
super(StockInAdmin,self).save_model(request,obj,form,change)
|
||||
if obj and obj.po:
|
||||
po_items = obj.po.poitem_set.filter(left_cnt__gt=0).all()
|
||||
for item in po_items:
|
||||
try:
|
||||
InItem.objects.get(po_item=item,master=obj)
|
||||
continue
|
||||
except Exception,e:
|
||||
pp = item.discount_price or item.price
|
||||
if decimal.Decimal(item.tax) > decimal.Decimal(0):
|
||||
pp = pp /(decimal.Decimal(1)+decimal.Decimal(item.tax))
|
||||
InItem.objects.create(warehouse=obj.warehouse,material=item.material,measure=item.measure,prop='+',
|
||||
po_item=item,master=obj,cnt=item.left_cnt,price=pp,batch=obj.batch,source=obj.code)
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
print obj
|
||||
if obj and obj.status == 9:
|
||||
return ['code','title','po','warehouse','batch','status']
|
||||
else:
|
||||
return ['status','amount']
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
if object_id:
|
||||
obj = StockIn.objects.get(id=object_id)
|
||||
if obj and obj.execute_time:
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(StockInAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
class StockOutAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'CK'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','title','project','status','out_time','out_amount']
|
||||
list_display_links = ['code','title']
|
||||
date_hierarchy = 'begin'
|
||||
inlines = [OutItemInline]
|
||||
raw_id_fields = ['project','wo','user']
|
||||
fields = (
|
||||
('code', 'status',),('project', ),('wo','user'),
|
||||
('title','amount',),('description',),
|
||||
)
|
||||
readonly_fields = ['status']
|
||||
extra_buttons = [{'href':'out','title':_('Action Stock Out')}]
|
||||
search_fields = ['code','title','user__username']
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
if object_id:
|
||||
obj = StockOut.objects.get(id=object_id)
|
||||
if obj and obj.execute_time:
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(StockOutAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj and obj.user is None:
|
||||
obj.user = request.user
|
||||
super(StockOutAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
|
||||
class InitialInventoryAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'QC'
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
list_display = ['code','title','status']
|
||||
inlines = [InitItemInline]
|
||||
fields = ('code','title','org','status','amount','attach')
|
||||
readonly_fields = ['status','amount']
|
||||
extra_buttons = [{'href':'cin','title':_('Action Stock In')}]
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
if object_id:
|
||||
obj = InitialInventory.objects.get(id=object_id)
|
||||
if obj and obj.execute_time:
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(InitialInventoryAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
class InventoryAdmin(generic.BOAdmin):
|
||||
list_display = ['material','measure','warehouse','cnt','price']
|
||||
search_fields = ['material__name','material__code']
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
extra_context.update(dict(readonly=True))
|
||||
if object_id:
|
||||
inventory = Inventory.objects.get(id=object_id)
|
||||
material = inventory.material
|
||||
warehouse = inventory.warehouse
|
||||
detail = InOutDetail.objects.filter(material=material,warehouse=warehouse)
|
||||
extra_context.update(dict(detail=detail))
|
||||
|
||||
return super(InventoryAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
class ReturnItemInline(admin.TabularInline):
|
||||
model = ReturnItem
|
||||
fields = ['material','measure','warehouse','out_cnt','cnt']
|
||||
readonly_fields = ['material','measure','warehouse','out_cnt']
|
||||
extra = 0
|
||||
|
||||
|
||||
class WareReturnAdmin(generic.BOAdmin):
|
||||
"""
|
||||
|
||||
"""
|
||||
CODE_PREFIX = 'FK'
|
||||
CODE_NUMBER_WIDTH = 4
|
||||
list_display = ['code','title','out']
|
||||
fields = (
|
||||
('code',),('title',),('out',),('amount',),('status',)
|
||||
)
|
||||
readonly_fields = ['status']
|
||||
raw_id_fields = ['out']
|
||||
inlines = [ReturnItemInline]
|
||||
extra_buttons = [{'href':'cin','title':_('Action Ware Return')}]
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
if object_id :
|
||||
obj = WareReturn.objects.get(id=object_id)
|
||||
if obj.status == '9':
|
||||
extra_context = extra_context or {}
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(WareReturnAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
class AdjustItemInline(admin.TabularInline):
|
||||
model = AdjustItem
|
||||
fields = ['inventory','measure','warehouse','prop','cnt']
|
||||
readonly_fields = ['measure','warehouse']
|
||||
raw_id_fields = ['inventory']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class WareAdjustAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'TZ'
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
list_display = ['code','title','status']
|
||||
fields = (
|
||||
('code',),('title',),('description',),('status',)
|
||||
)
|
||||
readonly_fields = ['status']
|
||||
inlines = [AdjustItemInline]
|
||||
extra_buttons = [{'href':'adjust','title':_('Action Ware Adjust')}]
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
if object_id:
|
||||
obj = WareAdjust.objects.get(id=object_id)
|
||||
if obj and obj.status == '9':
|
||||
extra_context = extra_context or {}
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(WareAdjustAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
admin.site.register(StockIn,StockInAdmin)
|
||||
admin.site.register(StockOut,StockOutAdmin)
|
||||
admin.site.register(InitialInventory,InitialInventoryAdmin)
|
||||
admin.site.register(Inventory,InventoryAdmin)
|
||||
admin.site.register(WareReturn,WareReturnAdmin)
|
||||
admin.site.register(WareAdjust,WareAdjustAdmin)
|
||||
@@ -0,0 +1,11 @@
|
||||
# created at 15-5-23
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class MyAppConfig(AppConfig):
|
||||
name = 'invent'
|
||||
verbose_name = _("inventory manage")
|
||||
@@ -0,0 +1,493 @@
|
||||
# coding=utf-8
|
||||
import csv
|
||||
import os
|
||||
import datetime
|
||||
import decimal
|
||||
from django.db import transaction
|
||||
from django.db import models
|
||||
from django import forms
|
||||
from mis import settings
|
||||
from django.utils.text import force_text
|
||||
from django.db import transaction
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from common import const
|
||||
from basedata.models import Material,Warehouse,Measure,Organization,Project
|
||||
from selfhelp.models import WorkOrder
|
||||
from purchase.models import PurchaseOrder,POItem
|
||||
|
||||
|
||||
class Inventory(generic.BO):
|
||||
"""
|
||||
库存信息
|
||||
"""
|
||||
index_weight = 1
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
warehouse = models.ForeignKey(Warehouse,verbose_name=_("warehouse"))
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"))
|
||||
measure = models.ForeignKey(Measure,verbose_name=_("measure"))
|
||||
cnt = models.DecimalField(_("count"),max_digits=14,decimal_places=4)
|
||||
batch = models.CharField(_("batch"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
price = models.DecimalField(_("price"),max_digits=14,decimal_places=4)
|
||||
|
||||
def __unicode__(self):
|
||||
des = self.material.spec or ''
|
||||
return u'%s %s %s' % (self.material.code,self.material.name,des)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Inventory")
|
||||
verbose_name_plural = _("Inventory")
|
||||
ordering = ['material']
|
||||
|
||||
|
||||
class InitialInventory(generic.BO):
|
||||
"""
|
||||
期初库存
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('9', _("EXECUTED"))
|
||||
)
|
||||
index_weight = 9
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
execute_time = models.DateTimeField(_("execute time"),blank=True,null=True)
|
||||
attach = models.FileField(_('attach'),blank=True,null=True,upload_to='inventory',help_text=u'参考FD0002模板文档')
|
||||
amount = models.DecimalField(_('money of amount'),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
|
||||
super(InitialInventory,self).save(force_insert,force_update,using,update_fields)
|
||||
count = InitItem.objects.filter(master=self).count()
|
||||
if self.attach and count == 0:
|
||||
path = os.path.join(settings.MEDIA_ROOT,self.attach.name)
|
||||
reader = csv.reader(open(path,'r'))
|
||||
index = 0
|
||||
with transaction.atomic():
|
||||
for code,name,description,unit_code,unit_name,warehouse_code,warehouse_name,price,cnt in reader:
|
||||
index+=1
|
||||
if index == 1:
|
||||
continue
|
||||
|
||||
material = None
|
||||
measure = None
|
||||
house = None
|
||||
|
||||
try:
|
||||
measure = Measure.objects.get(code=unit_code)
|
||||
except Exception,e:
|
||||
measure = Measure.objects.create(code=unit_code,name=force_text(unit_name.decode('gbk')))
|
||||
|
||||
try:
|
||||
house = Warehouse.objects.get(code=warehouse_code)
|
||||
except Exception,e:
|
||||
house = Warehouse.objects.create(code=warehouse_code,name=force_text(warehouse_name.decode('gbk')))
|
||||
|
||||
try:
|
||||
material = Material.objects.get(code=code)
|
||||
except Exception,e:
|
||||
material = Material(code=code,name=force_text(name.decode('gbk')),spec=force_text(description.decode('gbk')),warehouse=house)
|
||||
material.stock_price = price
|
||||
material.save()
|
||||
InitItem.objects.create(master=self,material=material,price=price,cnt=cnt,warehouse=house,measure=measure,source=self.code)
|
||||
|
||||
def init_entry(self,request=None):
|
||||
"""
|
||||
执行期初入库
|
||||
"""
|
||||
count = InitItem.objects.filter(master=self).count()
|
||||
if count > 0:
|
||||
with transaction.atomic():
|
||||
total_amount = 0
|
||||
for item in InitItem.objects.filter(master=self).all():
|
||||
Inventory.objects.create(material=item.material,price=item.price,cnt=item.cnt,warehouse=item.warehouse,measure=item.measure)
|
||||
item.status = 1
|
||||
item.event_time = datetime.datetime.now()
|
||||
item.source = self.code
|
||||
item.save()
|
||||
item.material.stock_price = item.price
|
||||
if item.material.measure.count() == 0:
|
||||
item.material.measure.add(item.measure)
|
||||
item.material.save()
|
||||
total_amount += item.price*item.cnt
|
||||
self.amount = total_amount
|
||||
self.status = '9'
|
||||
self.execute_time = datetime.datetime.now()
|
||||
self.save()
|
||||
else:
|
||||
raise Exception(_("none material was found"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Initial Inventory")
|
||||
verbose_name_plural = _("Initial Inventory")
|
||||
|
||||
|
||||
class StockIn(generic.BO):
|
||||
"""
|
||||
入库单
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("QUALITY TESTING")),
|
||||
('9', _("EXECUTED"))
|
||||
)
|
||||
index_weight = 3
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
warehouse = models.ForeignKey(Warehouse,verbose_name=_("warehouse"))
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
execute_time = models.DateTimeField(_("execute time"),blank=True,null=True)
|
||||
po = models.ForeignKey(PurchaseOrder,verbose_name=_("purchase order"),null=True,limit_choices_to={"entry_status":"0"},blank=True)
|
||||
amount = models.DecimalField(_("stock in money of amount"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
batch = models.CharField(_("batch"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
|
||||
def money_of_amount(self):
|
||||
if self.amount:
|
||||
return self.amount
|
||||
else:
|
||||
return 0.00
|
||||
|
||||
def entry_time(self):
|
||||
if self.execute_time:
|
||||
return self.execute_time
|
||||
else:
|
||||
return ''
|
||||
|
||||
money_of_amount.short_description = _("stock in money of amount")
|
||||
entry_time.short_description = _("entry time")
|
||||
|
||||
def action_entry(self,request):
|
||||
"""
|
||||
执行入库操作
|
||||
"""
|
||||
if self.initem_set.count() > 0:
|
||||
with transaction.atomic():
|
||||
total_amount = decimal.Decimal(0)
|
||||
for item in self.initem_set.filter(status=0).all():
|
||||
try:
|
||||
inventory = Inventory.objects.get(warehouse=self.warehouse,material=item.material,measure=item.measure)
|
||||
if inventory.price != item.price:
|
||||
at = decimal.Decimal(inventory.price*inventory.cnt+item.price*item.cnt)
|
||||
ac = decimal.Decimal(inventory.cnt+item.cnt)
|
||||
average = at/ac
|
||||
inventory.price = average
|
||||
item.material.stock_price = average
|
||||
item.material.save()
|
||||
inventory.cnt += item.cnt
|
||||
inventory.save()
|
||||
total_amount += item.price*item.cnt
|
||||
except Exception,e:
|
||||
Inventory.objects.create(warehouse=self.warehouse,material=item.material,measure=item.measure,
|
||||
cnt=item.cnt,price=item.price,org=self.org)
|
||||
item.material.stock_price = item.price
|
||||
item.material.save()
|
||||
|
||||
item.status=1
|
||||
item.event_time = datetime.datetime.now()
|
||||
item.source = self.code
|
||||
item.save()
|
||||
total_amount += item.price*item.cnt
|
||||
# saving the purchase item
|
||||
item.po_item.is_in_stock = 1
|
||||
item.po_item.in_stock_time = datetime.datetime.now()
|
||||
item.po_item.entry_cnt = item.cnt
|
||||
|
||||
item.po_item.save()
|
||||
none_zero_left = POItem.objects.filter(po=item.po_item.po,left_cnt__gt=0).count()
|
||||
if none_zero_left == 0:
|
||||
item.po_item.po.status = '99'
|
||||
item.po_item.po.entry_status = 1
|
||||
item.po_item.po.entry_time = datetime.datetime.now()
|
||||
item.po_item.po.save()
|
||||
# saving stock in item status
|
||||
item.status = 1
|
||||
item.event_time = datetime.datetime.now()
|
||||
# updating master's record
|
||||
self.status = 9
|
||||
self.execute_time = datetime.datetime.now()
|
||||
self.amount = total_amount
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("StockIn")
|
||||
verbose_name_plural = _("StockIn")
|
||||
|
||||
|
||||
class StockOut(generic.BO):
|
||||
"""
|
||||
领料单
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("IN PROGRESS")),
|
||||
('9', _("EXECUTED"))
|
||||
)
|
||||
index_weight = 2
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
project = models.ForeignKey(Project,verbose_name=_("project"),blank=True,null=True)
|
||||
wo = models.ForeignKey(WorkOrder,verbose_name=_("work order"),blank=True,null=True)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
amount = models.DecimalField(_("money of amount"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("out user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
execute_time = models.DateTimeField(_("execute time"),blank=True,null=True)
|
||||
|
||||
def out_amount(self):
|
||||
return self.amount or ''
|
||||
|
||||
def out_time(self):
|
||||
return self.execute_time or ''
|
||||
|
||||
out_time.short_description = _('stock out time')
|
||||
out_amount.short_description = _('stock out amount')
|
||||
|
||||
def action_out(self,request=None):
|
||||
"""
|
||||
执行出库操作
|
||||
"""
|
||||
if self.outitem_set.count() > 0:
|
||||
with transaction.atomic():
|
||||
total = decimal.Decimal(0)
|
||||
for item in OutItem.objects.filter(master=self).all():
|
||||
if item.inventory.cnt < item.cnt:
|
||||
raise Exception('%s does not meets required' % item.material)
|
||||
if item.cnt:
|
||||
total += item.cnt * item.inventory.price
|
||||
item.inventory.cnt -= item.cnt
|
||||
item.status = 1
|
||||
item.price = item.inventory.price
|
||||
item.event_time = datetime.datetime.now()
|
||||
item.inventory.save()
|
||||
item.source=self.code
|
||||
item.save()
|
||||
if total > 0:
|
||||
self.amount = total
|
||||
self.status = '9'
|
||||
self.execute_time = datetime.datetime.now()
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("StockOut")
|
||||
verbose_name_plural = _("StockOut")
|
||||
|
||||
|
||||
class WareReturn(generic.BO):
|
||||
"""
|
||||
返库单
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("IN PROGRESS")),
|
||||
('9', _("EXECUTED"))
|
||||
)
|
||||
index_weight = 5
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
out = models.ForeignKey(StockOut,verbose_name=_('StockOut'))
|
||||
amount = models.DecimalField(_("money of amount"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("out user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
execute_time = models.DateTimeField(_("execute time"),blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(WareReturn,self).save(force_insert,force_update,using,update_fields)
|
||||
item_count = ReturnItem.objects.filter(master=self).count()
|
||||
if self.out and item_count == 0:
|
||||
for out_item in OutItem.objects.filter(master=self.out):
|
||||
ReturnItem.objects.create(master=self,out_item=out_item,material=out_item.material,price=out_item.price,
|
||||
measure=out_item.measure,warehouse=out_item.warehouse,out_cnt=out_item.cnt,cnt=out_item.cnt)
|
||||
|
||||
def action_return(self,request):
|
||||
with transaction.atomic():
|
||||
total_amount = decimal.Decimal(0)
|
||||
for item in ReturnItem.objects.filter(master=self):
|
||||
if item.cnt > item.out_item.cnt or item.cnt < 0:
|
||||
raise Exception('%s cnt is invalid,out is %s,return is %s' % (item.material,item.out_cnt,item.cnt))
|
||||
item.event_time = datetime.datetime.now()
|
||||
item.source = self.code
|
||||
item.status = 1
|
||||
item.out_item.inventory.cnt += item.cnt
|
||||
item.out_item.inventory.save()
|
||||
item.save()
|
||||
total_amount += item.price * item.cnt
|
||||
self.amount = total_amount
|
||||
self.status = '9'
|
||||
self.execute_time = datetime.datetime.now()
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("ware return")
|
||||
verbose_name_plural = _("ware return")
|
||||
|
||||
|
||||
class WareAdjust(generic.BO):
|
||||
"""
|
||||
库存调整
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("IN PROGRESS")),
|
||||
('9', _("EXECUTED"))
|
||||
)
|
||||
index_weight = 4
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("out user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
execute_time = models.DateTimeField(_("execute time"),blank=True,null=True)
|
||||
|
||||
def action_adjust(self,request):
|
||||
with transaction.atomic():
|
||||
for item in AdjustItem.objects.filter(master=self,status=0):
|
||||
inventory = item.inventory
|
||||
if item.prop == '+':
|
||||
inventory.cnt += item.cnt
|
||||
else:
|
||||
inventory.cnt -= item.cnt
|
||||
inventory.save()
|
||||
item.status = 1
|
||||
item.event_time = datetime.datetime.now()
|
||||
item.source = self.code
|
||||
item.save()
|
||||
self.status = '9'
|
||||
self.execute_time = datetime.datetime.now()
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("ware adjust")
|
||||
verbose_name_plural = _("ware adjust")
|
||||
|
||||
|
||||
class InOutDetail(models.Model):
|
||||
"""
|
||||
in out detail
|
||||
"""
|
||||
|
||||
PROP = (
|
||||
('+', _("PLUS")),
|
||||
('-', _("MINUS"))
|
||||
)
|
||||
|
||||
create_time = models.DateTimeField(_("create time"),auto_now_add=True)
|
||||
status = models.BooleanField(_("executed"),default=0)
|
||||
event_time = models.DateTimeField(_("event time"),blank=True,null=True)
|
||||
warehouse = models.ForeignKey(Warehouse,verbose_name=_("warehouse"),blank=True,null=True)
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"),limit_choices_to={"is_virtual":"0"},blank=True,null=True)
|
||||
measure = models.ForeignKey(Measure,verbose_name=_("measure"),blank=True,null=True)
|
||||
cnt = models.DecimalField(_("count"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
batch = models.CharField(_("batch"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
price = models.DecimalField(_("price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
prop = models.CharField(_("plus or minus property"),max_length=const.DB_CHAR_CODE_2,choices=PROP,default='+')
|
||||
source = models.CharField(_("source"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
|
||||
|
||||
class InitItem(InOutDetail):
|
||||
"""
|
||||
期初入库明细
|
||||
"""
|
||||
master = models.ForeignKey(InitialInventory)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("init item")
|
||||
verbose_name_plural = _("init item")
|
||||
|
||||
|
||||
class InItem(InOutDetail):
|
||||
"""
|
||||
入库单明细
|
||||
"""
|
||||
master = models.ForeignKey(StockIn)
|
||||
po_item = models.ForeignKey(POItem,verbose_name=_("po item"),blank=True,null=True)
|
||||
|
||||
def get_new_price(self):
|
||||
if self.po_item and self.master.warehouse:
|
||||
try:
|
||||
inventory = Inventory.objects.get(warehouse=self.master.warehouse,material=self.material,measure=self.measure)
|
||||
if inventory and self.price != inventory.price:
|
||||
total_amount = self.price*self.cnt+inventory.price*inventory.cnt
|
||||
total_count = self.cnt+inventory.cnt
|
||||
return total_amount/total_count
|
||||
except Exception,e:
|
||||
pass
|
||||
return self.price or ''
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("in item")
|
||||
verbose_name_plural = _("in item")
|
||||
|
||||
|
||||
class InItemForm(forms.ModelForm):
|
||||
|
||||
new_price = forms.CharField(label=_('new price'),required=False)
|
||||
|
||||
class Meta:
|
||||
model = InItem
|
||||
fields = ('material', 'measure', 'cnt', 'price')
|
||||
|
||||
|
||||
class OutItem(InOutDetail):
|
||||
"""
|
||||
出库单明细
|
||||
"""
|
||||
master = models.ForeignKey(StockOut)
|
||||
inventory = models.ForeignKey(Inventory,blank=True,null=True,verbose_name=_("inventory material"))
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
self.prop = '-'
|
||||
if self.inventory:
|
||||
self.material = self.inventory.material
|
||||
self.measure = self.inventory.measure
|
||||
self.warehouse = self.inventory.warehouse
|
||||
|
||||
super(OutItem,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("out item")
|
||||
verbose_name_plural = _("out item")
|
||||
|
||||
|
||||
class ReturnItem(InOutDetail):
|
||||
"""
|
||||
返库单明细
|
||||
"""
|
||||
master = models.ForeignKey(WareReturn)
|
||||
out_item = models.ForeignKey(OutItem,blank=True,null=True,verbose_name=_('out item'))
|
||||
out_cnt = models.DecimalField(_("out count"),max_digits=14,decimal_places=4)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("return item")
|
||||
verbose_name_plural = _("return item")
|
||||
|
||||
|
||||
class AdjustItem(InOutDetail):
|
||||
"""
|
||||
库存调整明细
|
||||
"""
|
||||
master = models.ForeignKey(WareAdjust)
|
||||
inventory = models.ForeignKey(Inventory,blank=True,null=True,verbose_name=_("inventory material"))
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.inventory:
|
||||
self.material = self.inventory.material
|
||||
self.measure = self.inventory.measure
|
||||
self.warehouse = self.inventory.warehouse
|
||||
super(AdjustItem,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("adjust item")
|
||||
verbose_name_plural = _("adjust item")
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.conf.urls import include, url,static
|
||||
import invent.views
|
||||
|
||||
urlpatterns = [
|
||||
url(r"stockin/(?P<object_id>\d+)/cin", 'invent.views.action_in'),
|
||||
url(r"initialinventory/(?P<object_id>\d+)/cin", 'invent.views.action_init'),
|
||||
url(r"stockout/(?P<object_id>\d+)/out", 'invent.views.action_out'),
|
||||
url(r"warereturn/(?P<object_id>\d+)/cin", 'invent.views.action_return'),
|
||||
url(r"wareadjust/(?P<object_id>\d+)/adjust", 'invent.views.action_adjust'),
|
||||
]
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
# coding=utf-8
|
||||
from django.contrib.admin import site
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import connection
|
||||
from django.http.response import HttpResponseRedirect
|
||||
from django.utils.encoding import force_text
|
||||
from django.template.response import TemplateResponse
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.models import User
|
||||
from invent.models import StockIn,StockOut,InitialInventory,WareReturn,WareAdjust
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
def action_in(request,object_id):
|
||||
"""
|
||||
入库操作
|
||||
:param request:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
title = _("Are you sure?")
|
||||
obj = StockIn.objects.get(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if request.POST.get("post"):
|
||||
try:
|
||||
obj.action_entry(request)
|
||||
messages.success(request,_('check in successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
|
||||
return HttpResponseRedirect("/admin/invent/stockin/%s"%(object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockin/in_confirmation.html', context)
|
||||
|
||||
|
||||
def action_out(request,object_id):
|
||||
"""
|
||||
出库操作
|
||||
:param request:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
title = _("Are you sure?")
|
||||
obj = StockOut.objects.get(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if request.POST.get("post"):
|
||||
try:
|
||||
obj.action_out(request)
|
||||
messages.success(request,_('check out successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
return HttpResponseRedirect("/admin/invent/stockout/%s"%(object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockout/out_confirmation.html', context)
|
||||
|
||||
|
||||
def action_init(request,object_id):
|
||||
"""
|
||||
期初入库操作
|
||||
:param request:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
title = _("Are you sure?")
|
||||
obj = InitialInventory.objects.get(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if request.POST.get("post"):
|
||||
try:
|
||||
obj.init_entry(request)
|
||||
messages.success(request,_('check in successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
|
||||
return HttpResponseRedirect("/admin/invent/initialinventory/%s"%(object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockin/in_confirmation.html', context)
|
||||
|
||||
|
||||
def action_return(request,object_id):
|
||||
"""
|
||||
返库操作
|
||||
:param request:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
title = _("Are you sure?")
|
||||
obj = WareReturn.objects.get(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if request.POST.get("post"):
|
||||
try:
|
||||
obj.action_return(request)
|
||||
messages.success(request,_('check in successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
|
||||
return HttpResponseRedirect("/admin/invent/warereturn/%s"%(object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockin/in_confirmation.html', context)
|
||||
|
||||
|
||||
def action_adjust(request,object_id):
|
||||
"""
|
||||
调整操作
|
||||
:param request:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
title = _("Are you sure?")
|
||||
obj = WareAdjust.objects.get(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if request.POST.get("post"):
|
||||
try:
|
||||
obj.action_adjust(request)
|
||||
messages.success(request,_('check in successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
|
||||
return HttpResponseRedirect("/admin/invent/wareadjust/%s"%(object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockin/in_confirmation.html', context)
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mis.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
||||
@@ -0,0 +1 @@
|
||||
__author__ = 'Administrator'
|
||||
@@ -0,0 +1,176 @@
|
||||
__author__ = 'zhugl'
|
||||
# created at 15-4-21
|
||||
#python import
|
||||
from threading import local
|
||||
from django.contrib import admin
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib.admin import ModelAdmin, actions
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||
from django.core.urlresolvers import NoReverseMatch, reverse
|
||||
from django.db.models.base import ModelBase
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.template.engine import Engine
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils import six
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.views.decorators.cache import never_cache
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
|
||||
_thread_local = local()
|
||||
|
||||
|
||||
def getuser():
|
||||
return getattr(_thread_local,'user',None)
|
||||
|
||||
|
||||
class RequestUser(object):
|
||||
|
||||
def process_request(self,request):
|
||||
django_user = getattr(request,'user',None)
|
||||
|
||||
if django_user is not None:
|
||||
_thread_local.user = django_user
|
||||
|
||||
def process_view(self, request, view_func, view_args, view_kwargs):
|
||||
app_weight = {'selfhelp':1,'purchase':3,'sale':2,'invent':4,'organ':5,'basedata':6,'syscfg':7,'workflow':8}
|
||||
if view_func.__name__ == 'index':
|
||||
app_dict = {}
|
||||
for model, model_admin in admin.site._registry.items():
|
||||
app_label = model._meta.app_label
|
||||
has_module_perms = model_admin.has_module_permission(request)
|
||||
|
||||
if has_module_perms:
|
||||
perms = model_admin.get_model_perms(request)
|
||||
if True in perms.values():
|
||||
info = (app_label, model._meta.model_name)
|
||||
model_dict = {
|
||||
'name': capfirst(model._meta.verbose_name_plural),
|
||||
'object_name': model._meta.object_name,
|
||||
'perms': perms,
|
||||
'weight':getattr(model,'index_weight',99)
|
||||
}
|
||||
if perms.get('change', False):
|
||||
try:
|
||||
model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin.site.name)
|
||||
except NoReverseMatch:
|
||||
pass
|
||||
if perms.get('add', False):
|
||||
try:
|
||||
model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin.site.name)
|
||||
except NoReverseMatch:
|
||||
pass
|
||||
if app_label in app_dict:
|
||||
app_dict[app_label]['models'].append(model_dict)
|
||||
else:
|
||||
app_dict[app_label] = {
|
||||
'name': apps.get_app_config(app_label).verbose_name,
|
||||
'app_label': app_label,
|
||||
'app_url': reverse(
|
||||
'admin:app_list',
|
||||
kwargs={'app_label': app_label},
|
||||
current_app=admin.site.name,
|
||||
),
|
||||
'has_module_perms': has_module_perms,
|
||||
'models': [model_dict],
|
||||
'weight':app_weight.get(app_label,99)
|
||||
}
|
||||
|
||||
app_list = list(six.itervalues(app_dict))
|
||||
app_list.sort(key=lambda x: x['weight'])
|
||||
|
||||
for app in app_list:
|
||||
app['models'].sort(key=lambda x: x['weight'])
|
||||
|
||||
context = dict(
|
||||
maxi_app_list=app_list,
|
||||
)
|
||||
try:
|
||||
todolist = self.get_my_task(request)
|
||||
context.update(dict(todolist = todolist))
|
||||
except Exception,e:
|
||||
pass
|
||||
# print context
|
||||
view_kwargs['extra_context'] = context
|
||||
|
||||
if view_func.__name__ == 'app_index':
|
||||
app_label = view_kwargs['app_label']
|
||||
app_name = apps.get_app_config(app_label).verbose_name
|
||||
app_dict = {}
|
||||
lib_dict = {}
|
||||
for model, model_admin in admin.site._registry.items():
|
||||
if model_admin.has_module_permission(request):
|
||||
label = model._meta.app_label
|
||||
is_current = False
|
||||
if label == app_label:
|
||||
is_current = True
|
||||
lib_dict[label] = {
|
||||
'name': apps.get_app_config(label).verbose_name,
|
||||
'app_label': label,
|
||||
'app_url': reverse(
|
||||
'admin:app_list',
|
||||
kwargs={'app_label': label},
|
||||
current_app=admin.site.name,
|
||||
),
|
||||
'weight':app_weight.get(label,99),
|
||||
'is_current':is_current,
|
||||
}
|
||||
if app_label == model._meta.app_label:
|
||||
has_module_perms = model_admin.has_module_permission(request)
|
||||
if not has_module_perms:
|
||||
raise PermissionDenied
|
||||
|
||||
perms = model_admin.get_model_perms(request)
|
||||
|
||||
if True in perms.values():
|
||||
info = (app_label, model._meta.model_name)
|
||||
model_dict = {
|
||||
'name': capfirst(model._meta.verbose_name_plural),
|
||||
'object_name': model._meta.object_name,
|
||||
'perms': perms,
|
||||
'weight':getattr(model,'index_weight',99)
|
||||
}
|
||||
if perms.get('change'):
|
||||
try:
|
||||
model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin.site.name)
|
||||
except NoReverseMatch:
|
||||
pass
|
||||
if perms.get('add'):
|
||||
try:
|
||||
model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin.site.name)
|
||||
except NoReverseMatch:
|
||||
pass
|
||||
if app_dict:
|
||||
app_dict['models'].append(model_dict),
|
||||
else:
|
||||
app_dict = {
|
||||
'name': app_name,
|
||||
'app_label': app_label,
|
||||
'app_url': '',
|
||||
'has_module_perms': has_module_perms,
|
||||
'models': [model_dict],
|
||||
}
|
||||
if not app_dict:
|
||||
raise Http404('The requested admin page does not exist.')
|
||||
# Sort the models alphabetically within each app.
|
||||
app_dict['models'].sort(key=lambda x: x['weight'])
|
||||
|
||||
app_lib = list(six.itervalues(lib_dict))
|
||||
app_lib.sort(key=lambda x: x['weight'])
|
||||
|
||||
context = dict(
|
||||
maxi_app_list=[app_dict],
|
||||
app_lib=app_lib,
|
||||
)
|
||||
view_kwargs['extra_context'] = context
|
||||
|
||||
def get_my_task(self,request):
|
||||
from workflow.models import TodoList
|
||||
if request and request.user:
|
||||
query = TodoList.objects.filter(user=request.user,status=0)
|
||||
if query.count() == 0:
|
||||
return None
|
||||
else:
|
||||
return query.all()[:10]
|
||||
@@ -0,0 +1,4 @@
|
||||
from django.contrib import admin
|
||||
|
||||
admin.site.site_header = 'Django-ERP'
|
||||
admin.site.site_title = 'ERP'
|
||||
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
Django settings for mis project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.8.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||
"""
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '_5%1a5zxdjsb-je@85!l34g--ve7!skhc%^c2n)3vqyhq)yq@c'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
|
||||
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'syscfg',
|
||||
'basedata',
|
||||
'organ',
|
||||
'workflow',
|
||||
'selfhelp',
|
||||
'hr',
|
||||
'invent',
|
||||
'purchase',
|
||||
'sale',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'midware.cuser.RequestUser',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'mis.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(BASE_DIR, 'templates')],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
TEMPLATE_THEME = 'default'
|
||||
|
||||
WSGI_APPLICATION = 'mis.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'HOST': '172.31.16.165',
|
||||
'NAME': 'erp',
|
||||
'USER': 'maximus',
|
||||
'PASSWORD': 'maximus1234',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'zh-CN'
|
||||
|
||||
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')]
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = False
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR,'static')
|
||||
STATICFILES_DIRS = (
|
||||
('css',os.path.join(STATIC_ROOT,'css')),
|
||||
('js',os.path.join(STATIC_ROOT,'js')),
|
||||
('img',os.path.join(STATIC_ROOT,'img')),
|
||||
)
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR,'upload')
|
||||
MEDIA_URL = '/upload/'
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
Django settings for mis project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.8.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||
"""
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '_5%1a5zxdjsb-je@85!l34g--ve7!skhc%^c2n)3vqyhq)yq@c'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'syscfg',
|
||||
'basedata',
|
||||
'organ',
|
||||
'workflow',
|
||||
'selfhelp',
|
||||
'hr',
|
||||
'invent',
|
||||
'purchase',
|
||||
'sale',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'midware.cuser.RequestUser',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'mis.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(BASE_DIR, 'templates')],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
TEMPLATE_THEME = 'default'
|
||||
|
||||
WSGI_APPLICATION = 'mis.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'HOST': 'localhost',
|
||||
'NAME': 'mis',
|
||||
'USER': 'root',
|
||||
'PASSWORD': 'root',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'zh-CN'
|
||||
|
||||
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')]
|
||||
|
||||
TIME_ZONE = 'Asia/Shanghai'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = False
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR,'static')
|
||||
STATICFILES_DIRS = (
|
||||
('css',os.path.join(STATIC_ROOT,'css')),
|
||||
('js',os.path.join(STATIC_ROOT,'js')),
|
||||
('img',os.path.join(STATIC_ROOT,'img')),
|
||||
)
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR,'upload')
|
||||
MEDIA_URL = '/upload/'
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
from django.conf.urls import include, url,static
|
||||
from django.contrib import admin
|
||||
from mis import settings
|
||||
import workflow
|
||||
import invent.urls
|
||||
import basedata.urls
|
||||
import selfhelp.urls
|
||||
import mis
|
||||
|
||||
urlpatterns = [
|
||||
# Examples:
|
||||
url(r'^$', 'mis.views.home'),
|
||||
# url(r'^blog/', include('blog.urls')),
|
||||
url(r"^admin/(?P<app>\w+)/(?P<model>\w+)/(?P<object_id>\d+)/start",'workflow.views.start'),
|
||||
url(r"^admin/(?P<app>\w+)/(?P<model>\w+)/(?P<object_id>\d+)/approve/(?P<operation>\d+)",'workflow.views.approve'),
|
||||
url(r"^admin/(?P<app>\w+)/(?P<model>\w+)/(?P<object_id>\d+)/restart/(?P<instance>\d+)",'workflow.views.restart'),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^admin/invent/', include(invent.urls)),
|
||||
url(r'^admin/basedata/', include(basedata.urls)),
|
||||
url(r'^admin/selfhelp/', include(selfhelp.urls)),
|
||||
]
|
||||
urlpatterns += static.static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)
|
||||
urlpatterns += static.static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.http.response import HttpResponseRedirect
|
||||
|
||||
|
||||
def home(request):
|
||||
return HttpResponseRedirect("/admin")
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for mis project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mis.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = 'organ.apps.OrganConfig'
|
||||
@@ -0,0 +1,68 @@
|
||||
# coding=utf-8
|
||||
from django.contrib import admin
|
||||
from common import generic
|
||||
from organ.models import Organization,OrgUnit,Position
|
||||
from basedata.models import BankAccount
|
||||
from basedata.admin import BankAccountInline
|
||||
import datetime
|
||||
|
||||
|
||||
class OrgAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'O'
|
||||
CODE_NUMBER_WIDTH = 2
|
||||
list_display = ['code','name','represent','lic_code','cer_code']
|
||||
|
||||
fields = (
|
||||
('name','code',),('short','pinyin',),
|
||||
('tax_num','tax_account',),('tax_address',),('represent','email',),
|
||||
('address','zipcode',),('contacts','phone',),('fax','website',),
|
||||
('lic_code','cer_code',),('license','certificate',),('status','weight',),
|
||||
)
|
||||
|
||||
inlines = [BankAccountInline]
|
||||
|
||||
|
||||
class OrgUnitAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'S'
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
list_display = ['code','name','unit_type','parent']
|
||||
list_display_links = ['code','name']
|
||||
fields = (
|
||||
('organization',),('parent',),('name','code',),('short','pinyin',),
|
||||
('unit_type',),('status','virtual',),('phone','fax',),
|
||||
('contacts','email',),('weight',),
|
||||
)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super(OrgUnitAdmin,self).get_queryset(request).filter(end__gt=datetime.date.today())
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj.parent and obj.parent.organization:
|
||||
obj.organization = obj.parent.organization
|
||||
obj.save()
|
||||
super(OrgUnitAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
|
||||
class PositionAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'P'
|
||||
CODE_NUMBER_WIDTH = 4
|
||||
list_display = ['code','name','unit','series','grade','parent']
|
||||
list_display_links = ['code','name']
|
||||
fields = (
|
||||
('unit',),('organization',),('parent',),('name','code',),('short','pinyin',),('series','grade',),
|
||||
('virtual','status'),('description',),('qualification',),('document',),('weight',),
|
||||
)
|
||||
readonly_fields = ['organization']
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super(PositionAdmin,self).get_queryset(request).filter(end__gt=datetime.date.today())
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj.unit:
|
||||
obj.organization = obj.unit.organization
|
||||
obj.save()
|
||||
super(PositionAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
admin.site.register(Position,PositionAdmin)
|
||||
admin.site.register(OrgUnit,OrgUnitAdmin)
|
||||
admin.site.register(Organization,OrgAdmin)
|
||||
@@ -0,0 +1,9 @@
|
||||
__author__ = 'zhugl'
|
||||
# created at 15-4-22
|
||||
from django.apps.config import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class OrganConfig(AppConfig):
|
||||
name = 'organ'
|
||||
verbose_name = _('organization')
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
# coding=utf-8
|
||||
from django.db import models
|
||||
from django.db import connection
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import const
|
||||
from common import generic
|
||||
|
||||
|
||||
class Organization(generic.BO):
|
||||
"""
|
||||
组织单位
|
||||
"""
|
||||
index_weight = 1
|
||||
code = models.CharField(_("organ code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
name = models.CharField(_("organ name"),max_length=const.DB_CHAR_NAME_120)
|
||||
short = models.CharField(_("short name"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
|
||||
tax_num = models.CharField(_("tax num"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
tax_address = models.CharField(_("tax address"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
tax_account = models.CharField(_("tax account"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
|
||||
represent = models.CharField(_("representative "),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
address = models.CharField(_("address"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
zipcode = models.CharField(_("zipcode"),max_length=const.DB_CHAR_CODE_8,blank=True,null=True)
|
||||
fax = models.CharField(_("fax"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
contacts = models.CharField(_("contacts"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
website = models.CharField(_("website"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
email = models.CharField(_("email"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
lic_code = models.CharField(_("license code"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
cer_code = models.CharField(_("certificate code"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
license = models.FileField(_("business license"),blank=True,null=True,upload_to='organ')
|
||||
certificate = models.FileField(_("organization code certificate"),blank=True,null=True,upload_to='organ')
|
||||
weight = models.IntegerField(_("weight"),default=9)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('organization')
|
||||
verbose_name_plural = _('organization')
|
||||
|
||||
|
||||
class OrgUnit(generic.BO):
|
||||
"""
|
||||
组织单元
|
||||
"""
|
||||
UNIT_LEVEL = (
|
||||
(1,_('BRANCH')),
|
||||
(2,_('DEPARTMENT')),
|
||||
(3,_('OFFICE')),
|
||||
(4,_('TEAM')),
|
||||
(5,_('COMMITTEE'))
|
||||
)
|
||||
index_weight = 2
|
||||
parent = models.ForeignKey('self',verbose_name=_("parent"),null=True,blank=True)
|
||||
organization = models.ForeignKey(Organization,verbose_name = _('organization'),null=True,blank=True)
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_8,blank=True,null=True)
|
||||
name = models.CharField(_("name"),max_length=const.DB_CHAR_NAME_120)
|
||||
short = models.CharField(_("short name"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
unit_type = models.IntegerField(_("type"),choices=UNIT_LEVEL,default=2)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
virtual = models.BooleanField(_("is virtual"),default=False)
|
||||
fax = models.CharField(_("fax"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
contacts = models.CharField(_("contacts"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
email = models.CharField(_("email"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
weight = models.IntegerField(_("weight"),default=99)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('org unit')
|
||||
verbose_name_plural = _('org unit')
|
||||
|
||||
|
||||
class Position(generic.BO):
|
||||
"""
|
||||
岗位
|
||||
"""
|
||||
SERIES = (
|
||||
('A',_("Admin Position")),
|
||||
('S',_("Sale Position")),
|
||||
('T',_("Technology Position")),
|
||||
('P',_("Produce Position")),
|
||||
)
|
||||
|
||||
GRADE = (
|
||||
('01', _("BASIC")),
|
||||
('02', _("MEDIUM")),
|
||||
('03', _("SENIOR")),
|
||||
('04', _("PROFESSOR")),
|
||||
('05', _("EXPERT")),
|
||||
)
|
||||
index_weight = 3
|
||||
unit = models.ForeignKey(OrgUnit,verbose_name=_('org unit'))
|
||||
organization = models.ForeignKey(Organization,verbose_name=_('organization'),null=True,blank=True)
|
||||
parent = models.ForeignKey('self',verbose_name=_("parent"),null=True,blank=True)
|
||||
code = models.CharField(_("position code"),max_length=const.DB_CHAR_CODE_8,blank=True,null=True)
|
||||
name = models.CharField(_("position name"),max_length=const.DB_CHAR_NAME_120)
|
||||
short = models.CharField(_("short name"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
pinyin = models.CharField(_("pinyin"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
series = models.CharField(_("position series"),max_length=1,default='A',choices=const.get_value_list('S014'))
|
||||
grade = models.CharField(_("position grade"),max_length=const.DB_CHAR_CODE_2,default='01',choices=const.get_value_list('S015'))
|
||||
virtual = models.BooleanField(_("is virtual"),default=False)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
description = models.TextField(_("position description"),blank=True,null=True)
|
||||
qualification = models.TextField(_("qualification"),blank=True,null=True)
|
||||
document = models.FileField(_("reference"),blank=True,null=True)
|
||||
weight = models.IntegerField(_("weight"),default=99)
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s' % (self.code,self.name)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('position')
|
||||
verbose_name_plural = _('position')
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1,3 @@
|
||||
# created at 15-6-27
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
@@ -0,0 +1,54 @@
|
||||
# created at 15-6-30
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
|
||||
class Operation(object):
|
||||
APPROVE = 1
|
||||
DENY = 3
|
||||
TERMINATE = 4
|
||||
|
||||
|
||||
class WorkflowAction(object):
|
||||
|
||||
name = ''
|
||||
description = ''
|
||||
|
||||
def action(self,request,obj,node_config,operation=Operation.APPROVE):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param obj:
|
||||
:param node_config:
|
||||
:return:
|
||||
"""
|
||||
|
||||
|
||||
class TestAction(WorkflowAction):
|
||||
name = 'action.test'
|
||||
|
||||
def action(self,request,obj,node_config,operation=Operation.APPROVE):
|
||||
print 'this is a workflow test action'
|
||||
print 'request user is %s,current node is %s'%(request.user,node_config)
|
||||
|
||||
|
||||
class WorkflowActionManager(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
actions = {}
|
||||
registed = False
|
||||
|
||||
def __init__(self):
|
||||
if WorkflowActionManager.registed:
|
||||
pass
|
||||
else:
|
||||
WorkflowActionManager.register(TestAction)
|
||||
WorkflowActionManager.registed = True
|
||||
|
||||
@classmethod
|
||||
def register(cls,action):
|
||||
if cls.actions.get(action.name):
|
||||
raise Exception('%s already exists,register failed'%action.name)
|
||||
if issubclass(action,WorkflowAction):
|
||||
WorkflowActionManager.actions[action.name] = action()
|
||||
@@ -0,0 +1,54 @@
|
||||
# created at 15-6-30
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
from workflow.models import Node
|
||||
|
||||
|
||||
class NextNodeHandler(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
name = ''
|
||||
description = ''
|
||||
|
||||
def handle(self,request,obj,node_config):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param obj:
|
||||
:param node_config:
|
||||
:return:workflow.models.Node
|
||||
"""
|
||||
return None
|
||||
|
||||
|
||||
class TestHandler(NextNodeHandler):
|
||||
name = 'project.budge.gt.10000'
|
||||
description = '预算金额大于10000,由总经理审批'
|
||||
|
||||
def handle(self,request,obj,node_config):
|
||||
budget = getattr(obj,'budget',None)
|
||||
if budget and budget > 10000:
|
||||
return Node.objects.filter(id=7).all()
|
||||
|
||||
|
||||
class NextNodeManager(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
handlers = {}
|
||||
registed = False
|
||||
|
||||
def __init__(self):
|
||||
if NextNodeManager.registed:
|
||||
pass
|
||||
else:
|
||||
NextNodeManager.register(TestHandler)
|
||||
NextNodeManager.registed = True
|
||||
|
||||
@classmethod
|
||||
def register(cls,handler):
|
||||
if cls.handlers.get(handler.name):
|
||||
raise Exception('%s already exists,register failed'%handler.name)
|
||||
if issubclass(handler,NextNodeHandler):
|
||||
NextNodeManager.handlers[handler.name] = handler()
|
||||
@@ -0,0 +1,67 @@
|
||||
# created at 15-6-30
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
|
||||
class NextUserHandler(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
name = ''
|
||||
description = ''
|
||||
|
||||
def handle(self,request,obj,node_config):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param obj:
|
||||
:param node_config:
|
||||
:return:django.contrib.auth.models.User[]
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class UpPosition(NextUserHandler):
|
||||
"""
|
||||
|
||||
"""
|
||||
name = 'up.position.user'
|
||||
|
||||
def handle(self,request,obj,node_config):
|
||||
from basedata.models import Employee,Position
|
||||
emp_query = Employee.objects.filter(user=request.user)
|
||||
if emp_query.count()>0:
|
||||
emp = emp_query.all()
|
||||
parent = []
|
||||
for e in emp:
|
||||
if e.position and e.position.parent:
|
||||
parent.append(e.position.parent)
|
||||
# print emp
|
||||
# print parent
|
||||
query2 = Employee.objects.filter(position__in=parent).exclude(user=None)
|
||||
return [x.user for x in query2.all()]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class NextUserManager(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
handlers = {}
|
||||
registed = False
|
||||
|
||||
def __init__(self):
|
||||
if NextUserManager.registed:
|
||||
pass
|
||||
else:
|
||||
NextUserManager.register(UpPosition)
|
||||
NextUserManager.registed = True
|
||||
|
||||
@classmethod
|
||||
def register(cls,handler):
|
||||
if cls.handlers.get(handler.name):
|
||||
raise Exception('%s already exists,register failed'%handler.name)
|
||||
if issubclass(handler,NextUserHandler):
|
||||
NextUserManager.handlers[handler.name] = handler()
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
# created at 15-6-27
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
import xlrd
|
||||
import os
|
||||
import datetime
|
||||
from mis import settings
|
||||
|
||||
|
||||
class Handler(object):
|
||||
name = ''
|
||||
|
||||
def handle(self,obj,f):
|
||||
pass
|
||||
|
||||
|
||||
class OPSHandler(Handler):
|
||||
"""
|
||||
导入基础信息:部门,岗位,职员
|
||||
"""
|
||||
name = 'OPS'
|
||||
|
||||
def handle(self,obj,f):
|
||||
if f and f.name.endswith('.xls'):
|
||||
path = os.path.join(settings.MEDIA_ROOT,f.name)
|
||||
workbook = xlrd.open_workbook(path)
|
||||
for sheet in workbook.sheets():
|
||||
if sheet.name == u'部门' or sheet.name == 'department':
|
||||
self.department(obj,sheet)
|
||||
elif sheet.name == u'岗位' or sheet.name == 'position':
|
||||
self.position(obj,sheet)
|
||||
elif sheet.name == u'职员' or sheet.name == 'employee':
|
||||
self.stuff(obj,sheet)
|
||||
|
||||
def department(self,obj,sheet):
|
||||
from organ.models import OrgUnit
|
||||
row_count = sheet.nrows
|
||||
if obj.is_clear:
|
||||
OrgUnit.objects.update(end=datetime.date.today())
|
||||
for row_index in range(1,row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
weight = 99
|
||||
if row[6]:
|
||||
weight = row[6]
|
||||
OrgUnit.objects.create(code=row[0],name=row[1],short=row[2],pinyin=row[3],begin=datetime.date.today(),
|
||||
end=datetime.date(9999,12,31),weight=weight)
|
||||
for row_index in range(1,row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
if len(row[4]) > 0:
|
||||
try:
|
||||
parent = OrgUnit.objects.get(code=row[4])
|
||||
OrgUnit.objects.filter(code=row[0]).update(parent=parent)
|
||||
except Exception,e:
|
||||
pass
|
||||
|
||||
def position(self,obj,sheet):
|
||||
from organ.models import Position,OrgUnit
|
||||
row_count = sheet.nrows
|
||||
if obj.is_clear:
|
||||
Position.objects.update(end=datetime.date.today())
|
||||
for row_index in range(1,row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
depart = None
|
||||
if len(row[4]) > 0:
|
||||
try:
|
||||
depart = OrgUnit.objects.filter(code=row[4],end__gt=datetime.date.today()).all()[0]
|
||||
except Exception,e:
|
||||
pass
|
||||
weight = 99
|
||||
if row[6]:
|
||||
weight = row[6]
|
||||
Position.objects.create(code=row[0],name=row[1],unit=depart,begin=datetime.date.today(),
|
||||
end=datetime.date(9999,12,31),weight=weight)
|
||||
for row_index in range(1,row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
if len(row[2]) > 0:
|
||||
try:
|
||||
parent = Position.objects.filter(code=row[2],end__gt=datetime.date.today()).all()[0]
|
||||
Position.objects.filter(code=row[0]).update(parent=parent)
|
||||
except Exception,e:
|
||||
pass
|
||||
|
||||
def stuff(self,obj,sheet):
|
||||
from organ.models import Position
|
||||
from basedata.models import Employee
|
||||
from django.contrib.auth.models import User,Group
|
||||
row_count = sheet.nrows
|
||||
try:
|
||||
group = Group.objects.get_by_natural_key(u'职员')
|
||||
except Exception,e:
|
||||
pass
|
||||
for row_index in range(1,row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
position = Position.objects.filter(code=row[8],end__gt=datetime.date.today()).all()[0]
|
||||
username = row[10]
|
||||
email = row[11]
|
||||
password = row[4][-6:]
|
||||
if position is None:
|
||||
raise Exception(u'职员%s-%s未分配岗位,或者您选择的岗位已失效,不可被引用'%(row[0],row[1]))
|
||||
try:
|
||||
employee = Employee.objects.get(code=row[0])
|
||||
if employee.position.code == row[8]:
|
||||
continue
|
||||
else:
|
||||
employee.position = position
|
||||
employee.save()
|
||||
except Exception,e:
|
||||
employee = Employee.objects.create(code=row[0],name=row[1],pinyin=row[2],gender=row[3],idcard=row[4],
|
||||
birthday=row[5],workday=row[6],startday=row[7],position=position)
|
||||
if username:
|
||||
try:
|
||||
user = User.objects.get_by_natural_key(username)
|
||||
except Exception,e:
|
||||
user = User.objects.create_user(username=username,password=password)
|
||||
user.is_staff = True
|
||||
user.is_active = True
|
||||
user.first_name = row[1]
|
||||
if email:
|
||||
user.email = email
|
||||
if group:
|
||||
user.groups.add(group)
|
||||
user.save()
|
||||
employee.user = user
|
||||
employee.save()
|
||||
|
||||
|
||||
class UserHandler(Handler):
|
||||
"""
|
||||
基础数据导入:用户
|
||||
"""
|
||||
name = 'admin.user'
|
||||
|
||||
def handle(self,obj,f):
|
||||
from django.contrib.auth.models import User,Group
|
||||
if f and f.name.endswith('.xls'):
|
||||
path = os.path.join(settings.MEDIA_ROOT,f.name)
|
||||
workbook = xlrd.open_workbook(path)
|
||||
sheet = workbook.sheet_by_index(0)
|
||||
row_count = sheet.nrows
|
||||
try:
|
||||
group = Group.objects.get_by_natural_key(u'职员')
|
||||
except Exception,e:
|
||||
pass
|
||||
|
||||
for row_index in range(2,row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
username = row[0]
|
||||
password = row[1]
|
||||
last_name = row[2]
|
||||
first_name = row[3]
|
||||
email = row[4]
|
||||
if username == '':
|
||||
continue
|
||||
try:
|
||||
user = User.objects.get_by_natural_key(username)
|
||||
except Exception,e:
|
||||
user = User.objects.create_user(username=username,password=password,email=email)
|
||||
user.is_staff = True
|
||||
user.is_active = True
|
||||
user.last_name = last_name
|
||||
user.first_name = first_name
|
||||
if group:
|
||||
user.groups.add(group)
|
||||
user.save()
|
||||
|
||||
|
||||
class ExcelManager(object):
|
||||
"""
|
||||
|
||||
"""
|
||||
handlers = {}
|
||||
|
||||
def __init__(self):
|
||||
ExcelManager.register(OPSHandler)
|
||||
ExcelManager.register(UserHandler)
|
||||
|
||||
@classmethod
|
||||
def register(cls,handler):
|
||||
if cls.handlers.get(handler.name):
|
||||
raise Exception('%s already exists,register failed'%handler.name)
|
||||
if issubclass(handler,Handler):
|
||||
ExcelManager.handlers[handler.name] = handler()
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "purchase.apps.MyAppConfig"
|
||||
@@ -0,0 +1,90 @@
|
||||
from django.contrib import admin
|
||||
from common import generic
|
||||
from purchase.models import PurchaseOrder,POItem,Invoice,Payment
|
||||
from basedata.models import Partner,BankAccount
|
||||
|
||||
|
||||
class POItemInline(admin.TabularInline):
|
||||
model = POItem
|
||||
fields = ('material', 'measure','price', 'cnt', 'tax', 'discount_price')
|
||||
raw_id_fields = ['material']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
class PurchaseOrderAdmin(generic.BOAdmin):
|
||||
"""
|
||||
|
||||
"""
|
||||
CODE_PREFIX = 'CG'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','title','order_date','partner','amount','discount_amount','payed_amount','invoice_amount','status']
|
||||
list_display_links = ['code','title']
|
||||
raw_id_fields = ['partner']
|
||||
fields = (
|
||||
('code','partner'),('order_date','arrive_date'),
|
||||
('title','status',),('description',),('amount','discount_amount'),('attach',),
|
||||
)
|
||||
readonly_fields = ['status','amount']
|
||||
inlines = [POItemInline]
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
if object_id:
|
||||
extra_context = extra_context or {}
|
||||
obj = PurchaseOrder.objects.get(id=object_id)
|
||||
if obj.status == '99':
|
||||
extra_context.update(dict(readonly=True))
|
||||
return super(PurchaseOrderAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
import datetime
|
||||
begin = datetime.date.today()
|
||||
end = begin + datetime.timedelta(30)
|
||||
return {'order_date':begin,'arrive_date':end}
|
||||
|
||||
|
||||
class PurchaseItemAdmin(generic.BOAdmin):
|
||||
list_display = ['po','vender','material','cnt','price','tax']
|
||||
readonly_fields = ['po','material','cnt','price','tax']
|
||||
|
||||
def get_queryset(self, request):
|
||||
return POItem.objects.filter(left_cnt__gt=0)
|
||||
|
||||
|
||||
class InvoiceAdmin(generic.BOAdmin):
|
||||
list_display = ['code','number','vo_date','po','partner','po_amount','vo_amount']
|
||||
readonly_fields = ['partner','po_amount']
|
||||
raw_id_fields = ['po']
|
||||
search_fields = ['po__code','partner__name']
|
||||
date_hierarchy = 'begin'
|
||||
fields = (
|
||||
('vo_date',),('po',),('po_amount','partner',),('code',),('number',),('vo_amount',),('file',)
|
||||
)
|
||||
|
||||
|
||||
class PaymentAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'PY'
|
||||
CODE_NUMBER_WIDTH = 4
|
||||
list_display = ['code','py_date','po','partner','po_amount','py_amount']
|
||||
readonly_fields = ['partner','po_amount']
|
||||
raw_id_fields = ['po']
|
||||
search_fields = ['po__code','partner__name']
|
||||
fields = (
|
||||
('py_date','code',),('po',),('partner','po_amount',),('py_amount',),('bank',),('response_code'),('memo',)
|
||||
)
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'bank':
|
||||
kwargs['queryset'] = BankAccount.objects.exclude(org__exact=None)
|
||||
return super(PaymentAdmin,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
admin.site.register(PurchaseOrder,PurchaseOrderAdmin)
|
||||
admin.site.register(POItem,PurchaseItemAdmin)
|
||||
admin.site.register(Invoice,InvoiceAdmin)
|
||||
admin.site.register(Payment,PaymentAdmin)
|
||||
@@ -0,0 +1,11 @@
|
||||
# created at 15-5-23
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class MyAppConfig(AppConfig):
|
||||
name = 'purchase'
|
||||
verbose_name = _("purchase manage")
|
||||
@@ -0,0 +1,221 @@
|
||||
# coding=utf-8
|
||||
import datetime
|
||||
import os
|
||||
import xlrd
|
||||
import decimal
|
||||
from django.db import transaction
|
||||
from django.db import models
|
||||
from django.db.models.aggregates import Sum
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.text import force_text
|
||||
from mis import settings
|
||||
from common import generic
|
||||
from common import const
|
||||
from selfhelp.models import WOItem
|
||||
from basedata.models import Material,Organization,Partner,Measure,BankAccount
|
||||
|
||||
|
||||
class PurchaseOrder(generic.BO):
|
||||
"""
|
||||
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("IN PROGRESS")),
|
||||
('4', _("DROP")),
|
||||
('9', _("APPROVED")),
|
||||
('99', _("ALREADY STOCK IN")),
|
||||
)
|
||||
index_weight = 1
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),limit_choices_to={"partner_type":"S"})
|
||||
order_date = models.DateField(_("order date"))
|
||||
arrive_date = models.DateField(_("arrive date"))
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
amount = models.DecimalField(_("money amount"),max_digits=12,decimal_places=2,blank=True,null=True,default=0.00)
|
||||
discount_amount = models.DecimalField(_("discount amount"),max_digits=12,decimal_places=2,blank=True,null=True,default=0.00)
|
||||
entry_status = models.BooleanField(_("entry status"),default=0)
|
||||
entry_time = models.DateTimeField(_("entry time"),blank=True,null=True)
|
||||
attach = models.FileField(_('attach'),blank=True,null=True,help_text=u'您可导入采购明细,模板请参考文档FD0008')
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s' % (self.code,self.title)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(PurchaseOrder,self).save(force_insert,force_update,using,update_fields)
|
||||
if self.discount_amount > 0:
|
||||
sql = 'UPDATE purchase_poitem a SET a.discount_price = ' \
|
||||
'a.price-((SELECT discount_amount/amount FROM purchase_purchaseorder WHERE id=%s)*a.amount/a.cnt) WHERE a.po_id = %s'
|
||||
params = [self.id,self.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
item_count = POItem.objects.filter(po=self).count()
|
||||
if self.attach and item_count == 0:
|
||||
path = os.path.join(settings.MEDIA_ROOT,self.attach.name)
|
||||
workbook = xlrd.open_workbook(path)
|
||||
sheet = workbook.sheet_by_index(0)
|
||||
row_count = sheet.nrows
|
||||
with transaction.atomic():
|
||||
total_amount = decimal.Decimal(0)
|
||||
for row_index in range(row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
if row_index == 0:
|
||||
doc_type = row[1]
|
||||
if doc_type.startswith('0'):
|
||||
break
|
||||
else:
|
||||
continue
|
||||
elif row_index < 3:
|
||||
continue
|
||||
|
||||
material = None
|
||||
measure = None
|
||||
|
||||
try:
|
||||
measure = Measure.objects.get(code=row[4])
|
||||
except Exception,e:
|
||||
measure = Measure.objects.create(code=row[4],name=force_text(row[5]))
|
||||
|
||||
try:
|
||||
material = Material.objects.get(code=row[0])
|
||||
except Exception,e:
|
||||
material = Material(code=row[0],name=force_text(row[1]),spec=force_text(row[2]))
|
||||
material.purchase_price = row[6]
|
||||
material.save()
|
||||
amount = decimal.Decimal(row[6])*decimal.Decimal(row[7])
|
||||
POItem.objects.create(po=self,material=material,measure=measure,cnt=row[7],price=row[6],amount=amount)
|
||||
total_amount += amount
|
||||
sql = 'update purchase_purchaseorder set amount = %s where id=%s'
|
||||
params = [total_amount,self.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
def invoice_amount(self):
|
||||
total = Invoice.objects.filter(po=self).aggregate(Sum('vo_amount')).get('vo_amount__sum') or 0.00
|
||||
return total
|
||||
|
||||
def payed_amount(self):
|
||||
return Payment.objects.filter(po=self).aggregate(Sum('py_amount')).get('py_amount__sum') or 0.00
|
||||
|
||||
invoice_amount.short_description = _('invoice amount')
|
||||
payed_amount.short_description = _('pay amount')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("purchase order")
|
||||
verbose_name_plural = _("purchase orders")
|
||||
|
||||
|
||||
class POItem(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
index_weight = 2
|
||||
po = models.ForeignKey(PurchaseOrder,verbose_name=_("purchase order"))
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"),limit_choices_to={"is_virtual":"0"})
|
||||
measure = models.ForeignKey(Measure,verbose_name=_("measure"),blank=True,null=True)
|
||||
price = models.DecimalField(_("price"),max_digits=12,decimal_places=4,blank=True,null=True)
|
||||
cnt = models.DecimalField(_("count"),max_digits=12,decimal_places=4,blank=True,null=True)
|
||||
discount_price = models.DecimalField(_("discount price"),max_digits=12,decimal_places=4,blank=True,null=True)
|
||||
amount = models.DecimalField(_("money of amount"),max_digits=12,decimal_places=2,blank=True,null=True)
|
||||
discount_amount = models.DecimalField(_("discount amount"),max_digits=12,decimal_places=2,blank=True,null=True)
|
||||
tax = models.CharField(_("tax rate"),max_length=const.DB_CHAR_CODE_6,choices=const.get_value_list('S052'),default='0.00')
|
||||
woitem = models.ForeignKey(WOItem,verbose_name=_("wo item"),blank=True,null=True)
|
||||
is_in_stock = models.BooleanField(_("is in stock"),default=0)
|
||||
in_stock_time = models.DateTimeField(_("execute time"),blank=True,null=True)
|
||||
entry_cnt = models.DecimalField(_("entry count"),max_digits=12,decimal_places=4,blank=True,null=True)
|
||||
left_cnt = models.DecimalField(_("left count"),max_digits=12,decimal_places=4,blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.price and self.cnt:
|
||||
money = self.price * self.cnt
|
||||
self.amount = money
|
||||
|
||||
if self.measure is None and self.material and self.material.measure.count() > 0:
|
||||
self.measure = self.material.measure.all()[0]
|
||||
|
||||
if self.is_in_stock:
|
||||
self.left_cnt -= self.entry_cnt
|
||||
else:
|
||||
self.left_cnt = self.cnt
|
||||
super(POItem,self).save(force_insert,force_update,using,update_fields)
|
||||
self.material.purchase_price = self.price
|
||||
self.material.save()
|
||||
sql = 'UPDATE purchase_purchaseorder SET amount = (SELECT SUM(a.price*a.cnt) AS amount FROM ' \
|
||||
'purchase_poitem a WHERE a.po_id = %s) WHERE id = %s'
|
||||
params = [self.po.id,self.po.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
def vender(self):
|
||||
return u'%s' % (self.po.partner)
|
||||
|
||||
vender.short_description = _("partner")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("po item")
|
||||
verbose_name_plural = _("po item")
|
||||
|
||||
|
||||
class Invoice(generic.BO):
|
||||
"""
|
||||
采购发票
|
||||
"""
|
||||
index_weight = 4
|
||||
vo_date = models.DateField(_("invoice date"),blank=True,null=True,default=datetime.date.today)
|
||||
code = models.CharField(_("invoice code"),max_length=const.DB_CHAR_NAME_20)
|
||||
number = models.CharField(_("invoice number"),max_length=const.DB_CHAR_NAME_20)
|
||||
po = models.ForeignKey(PurchaseOrder,verbose_name=_("purchase order"))
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),blank=True,null=True)
|
||||
po_amount = models.DecimalField(_("po amount"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
vo_amount = models.DecimalField(_("invoice amount"),max_digits=14,decimal_places=4)
|
||||
file = models.FileField(_("invoice file"),upload_to='invoice',blank=True,null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s %s" % (self.code,self.partner)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.po:
|
||||
self.partner = self.po.partner
|
||||
self.po_amount = self.po.amount
|
||||
super(Invoice,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Invoice")
|
||||
verbose_name_plural = _("Invoice")
|
||||
|
||||
|
||||
class Payment(generic.BO):
|
||||
"""
|
||||
采购付款
|
||||
"""
|
||||
index_weight = 3
|
||||
py_date = models.DateField(_("pay date"),blank=True,null=True,default=datetime.date.today)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
code = models.CharField(_("pay code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
po = models.ForeignKey(PurchaseOrder,verbose_name=_("purchase order"))
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),blank=True,null=True)
|
||||
po_amount = models.DecimalField(_("po amount"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
py_amount = models.DecimalField(_("pay amount"),max_digits=14,decimal_places=4)
|
||||
bank = models.ForeignKey(BankAccount,verbose_name=_("bank account"),blank=True,null=True)
|
||||
response_code = models.CharField(_("response code"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
memo = models.TextField(_("memo"),blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.po:
|
||||
self.partner = self.po.partner
|
||||
self.po_amount = self.po.amount
|
||||
super(Payment,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s %s" % (self.code,self.partner)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Payment")
|
||||
verbose_name_plural = _("Payment")
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "sale.apps.MyAppConfig"
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
from django.contrib import admin
|
||||
from common import generic
|
||||
from sale.models import SaleOrder,SaleItem,PaymentCollection,OfferSheet,OfferItem
|
||||
from basedata.models import Measure,BankAccount
|
||||
from common import generic
|
||||
import datetime
|
||||
|
||||
|
||||
class SaleItemInline(admin.TabularInline):
|
||||
model = SaleItem
|
||||
fields = ('material','measure','sale_price','discount_price','cnt','tax')
|
||||
raw_id_fields = ['material']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
class OfferItemInline(admin.TabularInline):
|
||||
model = OfferItem
|
||||
fields = ('material','brand','measure','cost_price','sale_price','discount_price','cnt','tax')
|
||||
raw_id_fields = ['material']
|
||||
readonly_fields = ['brand']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 3
|
||||
|
||||
|
||||
class SaleOrderAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
CODE_PREFIX = 'SO'
|
||||
inlines = [SaleItemInline]
|
||||
list_display = ['code','title','order_date','partner','amount','collection_amount']
|
||||
list_display_links = ['code','title']
|
||||
raw_id_fields = ['partner','user','org']
|
||||
fields = (
|
||||
('code','org',),('title','invoice_type',),('partner','user',),('order_date','deliver_date',),
|
||||
('contact','phone',),('deliver_address','fax',),('description',),('amount','discount_amount','status')
|
||||
)
|
||||
readonly_fields = ['amount','status']
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj:
|
||||
obj.user = request.user
|
||||
super(SaleOrderAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
today = datetime.datetime.today()
|
||||
deadline = today+datetime.timedelta(days=30)
|
||||
return {'order_date':today,'deliver_date':deadline}
|
||||
|
||||
|
||||
class OfferSheetAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
CODE_PREFIX = 'BJ'
|
||||
inlines = [OfferItemInline]
|
||||
list_display = ['code','title','offer_date','partner','amount']
|
||||
list_display_links = ['code','title']
|
||||
raw_id_fields = ['partner','user','org']
|
||||
fields = (
|
||||
('code','org',),('partner','user',),('offer_date','deliver_date',),('title',),
|
||||
('description',),('amount','discount_amount',),('attach'),
|
||||
)
|
||||
readonly_fields = ['amount']
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj:
|
||||
obj.user = request.user
|
||||
super(OfferSheetAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
today = datetime.datetime.today()
|
||||
deadline = today+datetime.timedelta(days=30)
|
||||
return {'offer_date':today,'deliver_date':deadline}
|
||||
|
||||
|
||||
class PaymentCollectionAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 4
|
||||
CODE_PREFIX = 'CP'
|
||||
list_display = ['code','so','partner','order_amount','collection_date','collection_amount']
|
||||
fields = (
|
||||
('code',),('collection_date',),('so',),('partner',),('order_amount','collection_amount',),('bank',),
|
||||
('memo',)
|
||||
)
|
||||
raw_id_fields = ['so','partner']
|
||||
readonly_fields = ['order_amount']
|
||||
list_display_links = ['code','so']
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name=='bank':
|
||||
kwargs['queryset'] = BankAccount.objects.exclude(org__exact=None)
|
||||
return super(PaymentCollectionAdmin,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
admin.site.register(SaleOrder,SaleOrderAdmin)
|
||||
admin.site.register(PaymentCollection,PaymentCollectionAdmin)
|
||||
admin.site.register(OfferSheet,OfferSheetAdmin)
|
||||
@@ -0,0 +1,11 @@
|
||||
# created at 15-5-23
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class MyAppConfig(AppConfig):
|
||||
name = 'sale'
|
||||
verbose_name = _("sale management")
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
# coding=utf-8
|
||||
import decimal
|
||||
import datetime
|
||||
import csv
|
||||
import os
|
||||
import xlrd
|
||||
from mis import settings
|
||||
from django.db import models
|
||||
from django.db import transaction
|
||||
from django.db.models.aggregates import Sum
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.text import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from common import const
|
||||
from basedata.models import Material,Project,Partner,Organization,Measure,BankAccount
|
||||
|
||||
|
||||
class SaleOrder(generic.BO):
|
||||
"""
|
||||
销售订单
|
||||
"""
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("IN PROGRESS")),
|
||||
('4', _("DROP")),
|
||||
('9', _("APPROVED")),
|
||||
('99', _("ALREADY STOCK OUT")),
|
||||
)
|
||||
index_weight = 2
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),limit_choices_to={"partner_type":"C"})
|
||||
order_date = models.DateField(_("order date"))
|
||||
deliver_date = models.DateField(_("deliver date"))
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_("memo"),blank=True,null=True)
|
||||
contact = models.CharField(_("contacts"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
fax = models.CharField(_("fax"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
deliver_address = models.CharField(_("deliver address"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
invoice_type = models.CharField(_("invoice type"),max_length=const.DB_CHAR_CODE_6,choices=const.get_value_list('S053'),default='10')
|
||||
|
||||
amount = models.DecimalField(_("money amount"),max_digits=12,decimal_places=2,blank=True,null=True,default=0.00)
|
||||
discount_amount = models.DecimalField(_("discount amount"),max_digits=12,decimal_places=2,blank=True,null=True,default=0.00)
|
||||
user = models.ForeignKey(User,verbose_name=_("sales man"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),max_length=const.DB_CHAR_CODE_2,default='0',choices=STATUS)
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s' % (self.code,self.title)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(SaleOrder,self).save(force_insert,force_update,using,update_fields)
|
||||
if self.discount_amount > 0:
|
||||
sql = 'UPDATE sale_saleitem a SET a.discount_price = a.sale_price - ' \
|
||||
'((SELECT discount_amount/amount FROM sale_saleorder WHERE id = %s) * (a.sale_price*a.cnt)/a.cnt) WHERE a.master_id = %s'
|
||||
params = [self.id,self.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
def collection_amount(self):
|
||||
return PaymentCollection.objects.filter(so=self).aggregate(Sum('collection_amount')).get('collection_amount__sum') or 0.00
|
||||
|
||||
collection_amount.short_description = _('collection amount')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('sale order')
|
||||
verbose_name_plural = _('sale order')
|
||||
|
||||
|
||||
class SaleItem(models.Model):
|
||||
"""
|
||||
订单明细
|
||||
"""
|
||||
master = models.ForeignKey(SaleOrder)
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"),limit_choices_to={"is_virtual":"0",'can_sale':'1'},blank=True,null=True)
|
||||
measure = models.ForeignKey(Measure,verbose_name=_("measure"),blank=True,null=True)
|
||||
cnt = models.DecimalField(_("count"),max_digits=14,decimal_places=4)
|
||||
stock_price = models.DecimalField(_("stock price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
sale_price = models.DecimalField(_("sale price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
discount_price = models.DecimalField(_("discount price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
tax = models.CharField(_("tax rate"),max_length=const.DB_CHAR_CODE_6,choices=const.get_value_list('S052'),default='0.00')
|
||||
create_time = models.DateTimeField(_("create time"),auto_now_add=True)
|
||||
status = models.BooleanField(_("executed"),default=0)
|
||||
event_time = models.DateTimeField(_("event time"),blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.material and self.material.measure.count() > 0:
|
||||
self.measure = self.material.measure.all()[0]
|
||||
if self.material.sale_price or self.material.stock_price:
|
||||
self.sale_price = self.material.sale_price or self.material.stock_price*decimal.Decimal(1.17)/decimal.Decimal(0.6)
|
||||
super(SaleItem,self).save(force_insert,force_update,using,update_fields)
|
||||
sql = 'update sale_saleorder set amount = (select sum(sale_price*cnt) from sale_saleitem where master_id=%s) where id=%s'
|
||||
params = [self.master.id,self.master.id]
|
||||
# print sql % (self.master.id,self.master.id)
|
||||
generic.update(sql,params)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('order detail')
|
||||
verbose_name_plural = _('order detail')
|
||||
|
||||
|
||||
class PaymentCollection(generic.BO):
|
||||
"""
|
||||
销售回款
|
||||
"""
|
||||
index_weight = 3
|
||||
collection_date = models.DateField(_("collection date"),blank=True,null=True,default=datetime.date.today)
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
code = models.CharField(_("collection code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
so = models.ForeignKey(SaleOrder,verbose_name=_("sale order"))
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),blank=True,null=True)
|
||||
order_amount = models.DecimalField(_("order amount"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
collection_amount = models.DecimalField(_("collection amount"),max_digits=14,decimal_places=4)
|
||||
bank = models.ForeignKey(BankAccount,verbose_name=_("bank account"),blank=True,null=True)
|
||||
memo = models.TextField(_("memo"),blank=True,null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s %s'%(self.code,self.so)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.so:
|
||||
self.partner = self.so.partner
|
||||
self.order_amount = self.so.amount
|
||||
if self.so.discount_amount > 0:
|
||||
self.order_amount -= self.so.discount_amount
|
||||
super(PaymentCollection,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Payment Collection')
|
||||
verbose_name_plural = _('Payment Collection')
|
||||
|
||||
|
||||
class OfferSheet(generic.BO):
|
||||
"""
|
||||
报价单
|
||||
"""
|
||||
index_weight = 1
|
||||
STATUS = (
|
||||
('0', _("NEW")),
|
||||
('1', _("IN PROGRESS")),
|
||||
('4', _("DROP")),
|
||||
('9', _("APPROVED")),
|
||||
)
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
partner = models.ForeignKey(Partner,verbose_name=_("partner"),limit_choices_to={"partner_type":"C"})
|
||||
offer_date = models.DateField(_("offer date"))
|
||||
deliver_date = models.DateField(_("deliver date"))
|
||||
org = models.ForeignKey(Organization,verbose_name=_("organization"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_("memo"),blank=True,null=True)
|
||||
|
||||
amount = models.DecimalField(_("money amount"),max_digits=12,decimal_places=2,blank=True,null=True,default=0.00)
|
||||
discount_amount = models.DecimalField(_("discount amount"),max_digits=12,decimal_places=2,blank=True,null=True,default=0.00)
|
||||
user = models.ForeignKey(User,verbose_name=_("offer man"),blank=True,null=True)
|
||||
|
||||
attach = models.FileField(_('offer sheet file'),blank=True,null=True,upload_to='offer sheet',help_text=u'您可导入报价明细,模板请参考文档FD0006')
|
||||
status = models.BooleanField(_("executed"),default=0)
|
||||
event_time = models.DateTimeField(_("event time"),blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
import decimal
|
||||
super(OfferSheet,self).save(force_insert,force_update,using,update_fields)
|
||||
if self.discount_amount > 0:
|
||||
sql = 'UPDATE sale_offeritem a SET a.discount_price = a.sale_price - ' \
|
||||
'((SELECT discount_amount/amount FROM sale_offersheet WHERE id = %s) * (a.sale_price*a.cnt)/a.cnt) WHERE a.master_id = %s'
|
||||
params = [self.id,self.id]
|
||||
# print sql % (self.id,self.id)
|
||||
generic.update(sql,params)
|
||||
|
||||
item_count = OfferItem.objects.filter(master=self).count()
|
||||
if self.attach and item_count == 0:
|
||||
path = os.path.join(settings.MEDIA_ROOT,self.attach.name)
|
||||
workbook = xlrd.open_workbook(path)
|
||||
sheet = workbook.sheet_by_index(0)
|
||||
row_count = sheet.nrows
|
||||
with transaction.atomic():
|
||||
total_amount = decimal.Decimal(0)
|
||||
for row_index in range(row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
if row_index == 0:
|
||||
doc_type = row[1]
|
||||
if doc_type.startswith('0'):
|
||||
break
|
||||
else:
|
||||
continue
|
||||
elif row_index < 3:
|
||||
continue
|
||||
|
||||
material = None
|
||||
measure = None
|
||||
|
||||
try:
|
||||
measure = Measure.objects.get(code=row[4])
|
||||
except Exception,e:
|
||||
measure = Measure.objects.create(code=row[4],name=force_text(row[5]))
|
||||
|
||||
try:
|
||||
material = Material.objects.get(code=row[0])
|
||||
except Exception,e:
|
||||
material = Material(code=row[0],name=force_text(row[1]),spec=force_text(row[2]))
|
||||
material.sale_price = row[6]
|
||||
material.purchase_price = row[7]
|
||||
material.save()
|
||||
OfferItem.objects.create(master=self,material=material,measure=measure,cnt=row[8],brand=force_text(row[3]),
|
||||
cost_price=row[7],sale_price=row[6])
|
||||
total_amount += decimal.Decimal(row[6])*decimal.Decimal(row[8])
|
||||
sql = 'update sale_offersheet set amount = %s where id=%s'
|
||||
params = [total_amount,self.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('offer sheet')
|
||||
verbose_name_plural = _('offer sheet')
|
||||
|
||||
|
||||
class OfferItem(models.Model):
|
||||
"""
|
||||
订单明细
|
||||
"""
|
||||
master = models.ForeignKey(OfferSheet)
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"),limit_choices_to={"is_virtual":"0",'can_sale':'1'},blank=True,null=True)
|
||||
measure = models.ForeignKey(Measure,verbose_name=_("measure"),blank=True,null=True)
|
||||
cnt = models.DecimalField(_("count"),max_digits=14,decimal_places=4)
|
||||
brand = models.CharField(_('brand'),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
cost_price = models.DecimalField(_("cost price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
stock_price = models.DecimalField(_("stock price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
sale_price = models.DecimalField(_("sale price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
discount_price = models.DecimalField(_("discount price"),max_digits=14,decimal_places=4,blank=True,null=True)
|
||||
tax = models.CharField(_("tax rate"),max_length=const.DB_CHAR_CODE_6,choices=const.get_value_list('S052'),default='0.00')
|
||||
create_time = models.DateTimeField(_("create time"),auto_now_add=True)
|
||||
status = models.BooleanField(_("executed"),default=0)
|
||||
event_time = models.DateTimeField(_("event time"),blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if self.material and self.material.measure.count() > 0:
|
||||
self.measure = self.material.measure.all()[0]
|
||||
if self.material.sale_price or self.material.stock_price:
|
||||
self.sale_price = self.material.sale_price or self.material.stock_price*decimal.Decimal(1.17)/decimal.Decimal(0.6)
|
||||
super(OfferItem,self).save(force_insert,force_update,using,update_fields)
|
||||
sql = 'update sale_offersheet set amount = (select sum(sale_price*cnt) from sale_offeritem where master_id=%s) where id=%s'
|
||||
params = [self.master.id,self.master.id]
|
||||
# print sql % (self.master.id,self.master.id)
|
||||
generic.update(sql,params)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('offer detail')
|
||||
verbose_name_plural = _('offer detail')
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "selfhelp.apps.MyAppConfig"
|
||||
@@ -0,0 +1,219 @@
|
||||
# coding=utf-8
|
||||
# coding = utf-8
|
||||
import datetime
|
||||
from django.contrib import admin
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.db.models.aggregates import Sum
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from common import const
|
||||
from basedata.models import Material,ExtraParam,Employee,Position
|
||||
from selfhelp.models import WorkOrder,WOExtraValue,WOItem,Reimbursement,ReimbursementItem,Loan,Enroll,Feedback,Activity
|
||||
|
||||
|
||||
class ParamValueInline(admin.TabularInline):
|
||||
model = WOExtraValue
|
||||
fields = ('param_name','param_value')
|
||||
readonly_fields = ['param_name']
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
|
||||
if db_field.name == 'param_name':
|
||||
app_info = generic.get_app_model_info_from_request(request)
|
||||
instance = app_info['obj']
|
||||
if instance:
|
||||
kwargs['queryset'] = ExtraParam.objects.filter(material=instance.service)
|
||||
|
||||
return super(ParamValueInline,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class ItemInline(admin.TabularInline):
|
||||
model = WOItem
|
||||
raw_id_fields = ['material']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class WorkOrderAdmin(generic.BOAdmin):
|
||||
"""
|
||||
|
||||
"""
|
||||
CODE_PREFIX = 'WO'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','begin','title','classification','business_domain','status']
|
||||
list_display_links = ['code','title']
|
||||
exclude = ['creator','modifier','creation','modification']
|
||||
search_fields = ['code','title']
|
||||
list_filter = ['classification','service','status']
|
||||
fields = (
|
||||
('begin','end',),
|
||||
('code','refer',),('classification','business_domain',),
|
||||
('service','project',),
|
||||
('title','status',),('description',),('attach',),('detail',)
|
||||
)
|
||||
readonly_fields = ['status']
|
||||
raw_id_fields = ['service','project','refer']
|
||||
inlines = [ItemInline,ParamValueInline]
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj.user is None:
|
||||
obj.user = request.user
|
||||
super(WorkOrderAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
import datetime
|
||||
td = datetime.date.today()
|
||||
end = td + datetime.timedelta(30)
|
||||
return {'begin':datetime.date.today, 'end':end}
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'refer':
|
||||
app_info = generic.get_app_model_info_from_request(request)
|
||||
if app_info and app_info['obj']:
|
||||
kwargs['queryset'] = WorkOrder.objects.exclude(id=app_info['id'])
|
||||
|
||||
return super(WorkOrderAdmin,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
|
||||
class LoanAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'JK'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','title','project','loan_amount','applier','status']
|
||||
list_display_links = ['code','title']
|
||||
readonly_fields = ['status','logout_time','logout_amount']
|
||||
raw_id_fields = ['project','user']
|
||||
fields = (
|
||||
('code',),('title','loan_amount',),('description',),('project'),('user','status'),('logout_time','logout_amount',),
|
||||
)
|
||||
extra_buttons = [{'href':'pay','title':_('pay')}]
|
||||
search_fields = ['code','title','user__username']
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
if object_id:
|
||||
try:
|
||||
obj = Loan.objects.get(id=object_id)
|
||||
if obj and obj.status == 'P':
|
||||
extra_context = extra_context or {}
|
||||
extra_context.update(dict(readonly=True))
|
||||
except Exception,e:
|
||||
pass
|
||||
return super(LoanAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj and obj.user is None:
|
||||
obj.user = request.user
|
||||
super(LoanAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
|
||||
class ReimbursementItemInline(admin.TabularInline):
|
||||
model = ReimbursementItem
|
||||
raw_id_fields = ['expense_account']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class ReimbursementAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'BX'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','title','project','amount','applier','status']
|
||||
list_display_links = ['code','title']
|
||||
inlines = [ReimbursementItemInline]
|
||||
raw_id_fields = ['project','wo','user','org']
|
||||
readonly_fields = ['loan_amount','pay_time','status','amount']
|
||||
fieldsets = [
|
||||
(None,{'fields':[('code','user'),('title','amount','status',),('description',),('project','wo',)]}),
|
||||
(_('fico'),{'fields':[('org',),('loan',),('logout_amount','pay_amount',)],'classes': ['collapse']})
|
||||
]
|
||||
extra_buttons = [{'href':'pay','title':_('pay')}]
|
||||
search_fields = ['code','title','project__code','project__name','user__username']
|
||||
date_hierarchy = 'begin'
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
apps = generic.get_app_model_info_from_request(request)
|
||||
obj = getattr(apps,'obj',None)
|
||||
current = request.user
|
||||
if obj:
|
||||
current = obj.user
|
||||
sm = Loan.objects.filter(user=current).aggregate(Sum('loan_amount')).get('loan_amount__sum') or 0.00
|
||||
return {'loan_amount':sm}
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj and obj.user is None:
|
||||
obj.user = request.user
|
||||
|
||||
super(ReimbursementAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'loan':
|
||||
apps = generic.get_app_model_info_from_request(request)
|
||||
current = request.user
|
||||
if apps:
|
||||
obj = apps.get('obj')
|
||||
current = obj.user
|
||||
if obj.status == 'P':
|
||||
kwargs['queryset']=Loan.objects.filter(id=obj.loan.id)
|
||||
else:
|
||||
kwargs['queryset']=Loan.objects.filter(user=current,is_clear=0)
|
||||
else:
|
||||
kwargs['queryset']=Loan.objects.filter(user=current,is_clear=0)
|
||||
return super(ReimbursementAdmin,self).formfield_for_foreignkey(db_field,request,**kwargs)
|
||||
|
||||
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
|
||||
if object_id:
|
||||
try:
|
||||
obj = Reimbursement.objects.get(id=object_id)
|
||||
if obj and obj.status == 'P':
|
||||
extra_context = extra_context or {}
|
||||
extra_context.update(dict(readonly=True))
|
||||
except Exception,e:
|
||||
pass
|
||||
return super(ReimbursementAdmin,self).changeform_view(request,object_id,form_url,extra_context)
|
||||
|
||||
|
||||
class EnrollInline(admin.TabularInline):
|
||||
model = Enroll
|
||||
|
||||
|
||||
class FeedbackInline(admin.TabularInline):
|
||||
model = Feedback
|
||||
|
||||
|
||||
class ActivityAdmin(generic.BOAdmin):
|
||||
CODE_PREFIX = 'AC'
|
||||
CODE_NUMBER_WIDTH = 5
|
||||
list_display = ['code','begin_time','end_time','title','classification','room']
|
||||
list_display_links = ['code','title']
|
||||
raw_id_fields = ['room','parent']
|
||||
fieldsets = [
|
||||
(None,{'fields':[('begin_time','end_time',),('title','classification',),('description',),
|
||||
('host','speaker',),('room','location',),('attach',)]}),
|
||||
(_('other info'),{'fields':[('mail_list',),('parent',),('mail_notice','short_message_notice','weixin_notice',)],'classes': ['collapse']})
|
||||
]
|
||||
|
||||
def get_changeform_initial_data(self, request):
|
||||
now = datetime.datetime.now()
|
||||
begin = now + datetime.timedelta(hours=12)
|
||||
end = begin + datetime.timedelta(hours=6)
|
||||
return {'begin_time':begin,'end_time':end}
|
||||
|
||||
admin.site.register(WorkOrder,WorkOrderAdmin)
|
||||
admin.site.register(Loan,LoanAdmin)
|
||||
admin.site.register(Reimbursement,ReimbursementAdmin)
|
||||
admin.site.register(Activity,ActivityAdmin)
|
||||
@@ -0,0 +1,11 @@
|
||||
# created at 15-5-23
|
||||
# coding=utf-8
|
||||
__author__ = 'zhugl'
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class MyAppConfig(AppConfig):
|
||||
name = 'selfhelp'
|
||||
verbose_name = _("self help")
|
||||
@@ -0,0 +1,330 @@
|
||||
# coding=utf-8
|
||||
import datetime
|
||||
import os
|
||||
import xlrd
|
||||
import decimal
|
||||
from django.db import transaction
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.text import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import generic
|
||||
from common import const
|
||||
from mis import settings
|
||||
from basedata.models import Material,ExtraParam,Project,ExpenseAccount,Measure
|
||||
from organ.models import OrgUnit
|
||||
|
||||
|
||||
class WorkOrder(generic.BO):
|
||||
"""
|
||||
|
||||
"""
|
||||
index_weight = 1
|
||||
code = models.CharField(_("workorder code"),blank=True,null=True,max_length=const.DB_CHAR_CODE_10)
|
||||
refer = models.ForeignKey("self",verbose_name=_("refer wo"),blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_120)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
business_domain = models.CharField(_("business domain"),max_length=const.DB_CHAR_CODE_4,choices=const.get_value_list('S045'),default='OT')
|
||||
classification = models.CharField(_("classification"),max_length=const.DB_CHAR_CODE_4,choices=const.get_value_list('S044'),default='D')
|
||||
service = models.ForeignKey(Material,verbose_name=_("service name"),null=True,blank=True,limit_choices_to={"is_virtual":"1"})
|
||||
project = models.ForeignKey(Project,verbose_name=_("project"),null=True,blank=True)
|
||||
status = models.CharField(_("status"),blank=True,null=True,default='NEW',max_length=const.DB_CHAR_CODE_6,choices=const.get_value_list('S046'))
|
||||
answer = models.TextField(_("answer"),blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
attach = models.FileField(_('attach'),blank=True,null=True,help_text=u'工单附件,不导入明细。')
|
||||
detail = models.FileField(_('to be imported detail'),blank=True,null=True,help_text=u'您可导入需求明细,模板请参考文档FD0007')
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s-%s" % (self.code,self.title)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(WorkOrder,self).save(force_insert,force_update,using,update_fields)
|
||||
if self.service:
|
||||
material = self.service
|
||||
if self.woextravalue_set.count() < 1 and material.extraparam_set and material.extraparam_set.count() > 0:
|
||||
for param in material.extraparam_set.all():
|
||||
extra_param = WOExtraValue.objects.create(workorder=self,param_name=param)
|
||||
self.woextravalue_set.add(extra_param)
|
||||
item_count = WOItem.objects.filter(workorder=self).count()
|
||||
if self.detail and item_count == 0:
|
||||
path = os.path.join(settings.MEDIA_ROOT,self.detail.name)
|
||||
workbook = xlrd.open_workbook(path)
|
||||
sheet = workbook.sheet_by_index(0)
|
||||
row_count = sheet.nrows
|
||||
with transaction.atomic():
|
||||
for row_index in range(row_count):
|
||||
row = sheet.row_values(row_index)
|
||||
if row_index == 0:
|
||||
doc_type = row[1]
|
||||
if doc_type.startswith('0'):
|
||||
break
|
||||
else:
|
||||
continue
|
||||
elif row_index < 3:
|
||||
continue
|
||||
material = None
|
||||
measure = None
|
||||
try:
|
||||
measure = Measure.objects.get(code=row[4])
|
||||
except Exception,e:
|
||||
measure = Measure.objects.create(code=row[4],name=force_text(row[5]))
|
||||
try:
|
||||
material = Material.objects.get(code=row[0])
|
||||
except Exception,e:
|
||||
material = Material(code=row[0],name=force_text(row[1]),spec=force_text(row[2]))
|
||||
material.save()
|
||||
WOItem.objects.create(workorder=self,material=material,measure=measure,amount=row[6])
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workorder apply")
|
||||
verbose_name_plural = _("workorder apply")
|
||||
|
||||
class Media:
|
||||
js = ('js/workorder.js',)
|
||||
|
||||
|
||||
class WOExtraValue(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
workorder = models.ForeignKey(WorkOrder,verbose_name=_("workorder"))
|
||||
param_name = models.ForeignKey(ExtraParam,verbose_name=_("extra param"))
|
||||
param_value = models.CharField(_("param value"),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("extra value")
|
||||
verbose_name_plural = _("extra values")
|
||||
|
||||
|
||||
class WOItem(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
workorder = models.ForeignKey(WorkOrder,verbose_name=_("workorder"))
|
||||
material = models.ForeignKey(Material,verbose_name=_("material"),null=True,blank=True,limit_choices_to={"is_virtual":"0"})
|
||||
amount = models.DecimalField(_("amount"),max_digits=10,decimal_places=4,blank=True,null=True)
|
||||
measure = models.ForeignKey(Measure,verbose_name=_('measure'),blank=True,null=True)
|
||||
price = models.DecimalField(_("price"),max_digits=10,decimal_places=4,blank=True,null=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workorder item")
|
||||
verbose_name_plural = _("workorder items")
|
||||
|
||||
|
||||
class Loan(generic.BO):
|
||||
"""
|
||||
|
||||
"""
|
||||
LOAD_STATUS = (
|
||||
('N',_("NEW")),
|
||||
('I',_("IN PROGRESS")),
|
||||
('A',_("APPROVED")),
|
||||
('P',_("PAYED"))
|
||||
)
|
||||
index_weight = 3
|
||||
code = models.CharField(_("loan code"),max_length=const.DB_CHAR_CODE_10,blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_120)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
project = models.ForeignKey(Project,verbose_name=_("project"))
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
status = models.CharField(_("status"),blank=True,null=True,default='N',max_length=const.DB_CHAR_CODE_2,choices=LOAD_STATUS)
|
||||
logout_time = models.DateTimeField(_("logout time"),blank=True,null=True)
|
||||
loan_amount = models.DecimalField(_("loan amount"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
logout_amount = models.DecimalField(_("logout amount"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
pay_user = models.CharField(_('pay user'),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
pay_time = models.DateTimeField(_('pay time'),blank=True,null=True)
|
||||
is_clear = models.BooleanField(_('is clear'),default=False)
|
||||
|
||||
def __unicode__(self):
|
||||
import decimal
|
||||
left = self.loan_amount
|
||||
left -= self.logout_amount or decimal.Decimal(0.00)
|
||||
name = '%s%s'%(self.user.last_name,self.user.first_name)
|
||||
return '%s %s %s J:%.2f Y:%.2f' % (self.code,name,self.title,self.loan_amount,left)
|
||||
|
||||
def applier(self):
|
||||
return u'%s%s'%(self.user.last_name,self.user.first_name)
|
||||
|
||||
applier.short_description = _('applier')
|
||||
|
||||
def action_pay(self,request):
|
||||
self.pay_time = datetime.datetime.now()
|
||||
self.pay_user = request.user.username
|
||||
self.status = 'P'
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("loan")
|
||||
verbose_name_plural = _("loans")
|
||||
permissions = (
|
||||
('financial_pay',_("financial pay")),
|
||||
)
|
||||
|
||||
|
||||
class Reimbursement(generic.BO):
|
||||
"""
|
||||
|
||||
"""
|
||||
REIM_STATUS = (
|
||||
('N',_("NEW")),
|
||||
('I',_("IN PROGRESS")),
|
||||
('A',_("APPROVED")),
|
||||
('P',_("PAYED"))
|
||||
)
|
||||
index_weight = 2
|
||||
code = models.CharField(_("fee code"),max_length=const.DB_CHAR_CODE_10,blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_120)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
project = models.ForeignKey(Project,verbose_name=_("project"))
|
||||
wo = models.ForeignKey(WorkOrder,verbose_name=_("work order"),null=True,blank=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("user"),blank=True,null=True)
|
||||
org = models.ForeignKey(OrgUnit,verbose_name=_("cost center"),blank=True,null=True)
|
||||
bank_account = models.CharField(_("bank account"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
|
||||
status = models.CharField(_("status"),blank=True,null=True,default='N',max_length=const.DB_CHAR_CODE_2,choices=REIM_STATUS)
|
||||
amount = models.DecimalField(_("amount of money"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
loan = models.ForeignKey(Loan,verbose_name=_("loan record"),blank=True,null=True)
|
||||
loan_amount = models.DecimalField(_("loan amount"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
logout_amount = models.DecimalField(_("logout amount"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
pay_amount = models.DecimalField(_("pay amount"),max_digits=10,decimal_places=2,blank=True,null=True)
|
||||
pay_time = models.DateTimeField(_("pay time"),blank=True,null=True)
|
||||
pay_user = models.CharField(_('pay user'),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
|
||||
def applier(self):
|
||||
return u'%s%s'%(self.user.last_name,self.user.first_name)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
import decimal
|
||||
if self.loan:
|
||||
left = self.loan.loan_amount
|
||||
left -= self.loan.logout_amount or decimal.Decimal(0.00)
|
||||
if self.logout_amount is None or self.logout_amount == '':
|
||||
if self.amount < left:
|
||||
self.logout_amount = self.amount
|
||||
else:
|
||||
self.logout_amount = left
|
||||
self.pay_amount = self.amount
|
||||
if self.logout_amount:
|
||||
self.pay_amount -= self.logout_amount
|
||||
super(Reimbursement,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
def action_pay(self,request):
|
||||
if self.loan:
|
||||
if self.logout_amount is None or self.logout_amount == '':
|
||||
self.logout_amount = self.amount
|
||||
if self.logout_amount < 0:
|
||||
raise Exception(u'核销金额小于0')
|
||||
|
||||
if self.loan.logout_amount is None:
|
||||
self.loan.logout_amount = self.logout_amount
|
||||
else:
|
||||
self.loan.logout_amount += self.logout_amount
|
||||
|
||||
if self.loan.loan_amount == self.loan.logout_amount:
|
||||
self.loan.is_clear=True
|
||||
|
||||
self.loan.logout_time = datetime.datetime.now()
|
||||
self.loan.save()
|
||||
|
||||
if self.amount > self.logout_amount:
|
||||
self.pay_amount = self.amount - self.logout_amount
|
||||
|
||||
self.pay_time = datetime.datetime.now()
|
||||
self.pay_user = request.user.username
|
||||
self.status = 'P'
|
||||
self.save()
|
||||
|
||||
applier.short_description = _('applier')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("reimbursement")
|
||||
verbose_name_plural = _("reimbursements")
|
||||
permissions = (
|
||||
('financial_pay',_("financial pay")),
|
||||
)
|
||||
|
||||
|
||||
class ReimbursementItem(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
import datetime
|
||||
reimbursement = models.ForeignKey(Reimbursement,verbose_name=_("reimbursement"))
|
||||
expense_account = models.ForeignKey(ExpenseAccount,verbose_name=_("expenses account"))
|
||||
begin = models.DateField(_("occur date"),default=datetime.date.today)
|
||||
amount = models.DecimalField(_("amount of money"),max_digits=10,decimal_places=2)
|
||||
memo = models.CharField(_("memo"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(ReimbursementItem,self).save(force_insert,force_update,using,update_fields)
|
||||
sql = 'UPDATE selfhelp_reimbursement SET amount = (SELECT SUM(amount) FROM selfhelp_reimbursementitem WHERE reimbursement_id = %s) WHERE id = %s'
|
||||
params = [self.reimbursement.id,self.reimbursement.id]
|
||||
generic.update(sql,params)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("fee item")
|
||||
verbose_name_plural = _("fee items")
|
||||
|
||||
|
||||
class Activity(generic.BO):
|
||||
"""
|
||||
|
||||
"""
|
||||
CLASSIFICATION = (
|
||||
('T',_("Train")),
|
||||
('M',_("Meeting")),
|
||||
('G',_("Community")),
|
||||
)
|
||||
index_index_weight = 4
|
||||
begin_time = models.DateTimeField(_('begin time'))
|
||||
end_time = models.DateTimeField(_('end time'))
|
||||
enroll_deadline = models.DateTimeField(_('enroll deadline'),blank=True,null=True)
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
|
||||
title = models.CharField(_("title"),max_length=const.DB_CHAR_NAME_120)
|
||||
parent = models.ForeignKey('self',verbose_name=_("parent"),blank=True,null=True)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
host = models.CharField(_("host"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
speaker = models.CharField(_("speaker"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
accept_enroll = models.BooleanField(_("accept enroll"),default=1)
|
||||
room = models.ForeignKey(Material,verbose_name=_("room"),blank=True,null=True,limit_choices_to={'tp':20})
|
||||
location = models.CharField(_("location"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
classification = models.CharField(_("classification"),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=CLASSIFICATION,default='M')
|
||||
mail_list = models.TextField(_("mail list"),blank=True,null=True)
|
||||
mail_notice = models.BooleanField(_("mail notice"),default=1)
|
||||
short_message_notice = models.BooleanField(_("short message notice"),default=1)
|
||||
weixin_notice = models.BooleanField(_("weixin notice"),default=1)
|
||||
status = models.BooleanField(_("published"),default=0)
|
||||
publish_time = models.DateTimeField(_("publish time"),blank=True,null=True)
|
||||
attach = models.FileField(_("attach"),blank=True,null=True,upload_to='activity')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("activity")
|
||||
verbose_name_plural = _("activities")
|
||||
|
||||
|
||||
class Feedback(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
RANK = (
|
||||
('A','A'),
|
||||
('B','B'),
|
||||
('C','C'),
|
||||
('D','D'),
|
||||
)
|
||||
activity = models.ForeignKey(Activity)
|
||||
user = models.ForeignKey(User)
|
||||
feed_time = models.DateTimeField(_("feedback time"),auto_now_add=True)
|
||||
rank = models.CharField(_('rank'),max_length=const.DB_CHAR_CODE_2,blank=True,null=True,choices=RANK,default='B')
|
||||
comment = models.CharField(_("suggest"),blank=True,null=True,max_length=const.DB_CHAR_NAME_80)
|
||||
|
||||
|
||||
class Enroll(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
activity = models.ForeignKey(Activity)
|
||||
user = models.ForeignKey(User)
|
||||
enroll_time = models.DateTimeField(_("enroll time"),auto_now_add=True)
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,6 @@
|
||||
from django.conf.urls import include, url,static
|
||||
import selfhelp.views
|
||||
|
||||
urlpatterns = [
|
||||
url(r"(?P<model>\w+)/(?P<object_id>\d+)/pay", 'selfhelp.views.pay_action'),
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
# coding=utf-8
|
||||
from django.contrib.admin import site
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import connection
|
||||
from django.http.response import HttpResponseRedirect
|
||||
from django.utils.encoding import force_text
|
||||
from django.template.response import TemplateResponse
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
|
||||
def pay_action(request,model,object_id):
|
||||
title = _("Are you sure?")
|
||||
ct = ContentType.objects.get(app_label='selfhelp',model=model)
|
||||
obj = ct.get_object_for_this_type(id=int(object_id))
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
if model == 'reimbursement':
|
||||
loan = obj.loan
|
||||
amount = obj.logout_amount
|
||||
if loan and (amount is None or amount< 0):
|
||||
messages.error(request,u'您选择了借款单据,但是未正确填写核销金额,请在\'财务信息\'栏目中更正')
|
||||
return HttpResponseRedirect("/admin/selfhelp/%s/%s"%(model,object_id))
|
||||
|
||||
if request.POST.get("post"):
|
||||
try:
|
||||
obj.action_pay(request)
|
||||
messages.success(request,_('action successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
|
||||
return HttpResponseRedirect("/admin/selfhelp/%s/%s"%(model,object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
action_name=_('pay')
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'admin/invent/stockin/in_confirmation.html', context)
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
table#workflow-history{
|
||||
width:100%
|
||||
}
|
||||
table#workflow-history tbody th,table#workflow-history tbody td.col {
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.submitlink {
|
||||
padding-left: 12px;
|
||||
background: url(../img/icon-yes.gif) 0 .25em no-repeat;
|
||||
}
|
||||
|
||||
a.submitlink:link, a.submitlink:visited {
|
||||
color: #CC3434;
|
||||
}
|
||||
|
||||
a.submitlink:hover {
|
||||
color: #993333;
|
||||
}
|
||||
|
||||
label.control{
|
||||
width:4em;
|
||||
}
|
||||
|
||||
p.next-node{
|
||||
font-weight:bold;
|
||||
}
|
||||
ul.node-users{
|
||||
list-style:none;
|
||||
}
|
||||
p.tooltip{
|
||||
color:#999;
|
||||
}
|
||||
li.done-link{
|
||||
padding-left: 12px;
|
||||
background: url(../img/icon_yes.gif) 0 .2em no-repeat;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 122 B |
Binary file not shown.
|
After Width: | Height: | Size: 253 B |
Binary file not shown.
|
After Width: | Height: | Size: 299 B |
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
author:zhugl
|
||||
date:2015-05-15
|
||||
*/
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
/**
|
||||
set operation type
|
||||
*/
|
||||
$("fieldset.workflow input[type='radio']").on('click',function(){
|
||||
operation = $(this).val();
|
||||
next = "approve/"+operation;
|
||||
$("#workflow_approve").attr("href",next);
|
||||
});
|
||||
try{
|
||||
$("div.inline-group table tbody tr.form-row").removeClass('has_original');
|
||||
$("div.inline-group table tbody tr.form-row td:first-child").find('p').hide();
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
});
|
||||
})(django.jQuery);
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Created by Administrator on 15-5-23.
|
||||
*/
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
/**
|
||||
set operation type
|
||||
*/
|
||||
$("#woextravalue_set-group select").attr('readonly','true')
|
||||
});
|
||||
})(django.jQuery);
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
default_app_config = 'syscfg.apps.SysConfig'
|
||||
@@ -0,0 +1,53 @@
|
||||
# coding=utf-8
|
||||
from django.contrib import admin
|
||||
from django.forms import ModelForm,DateField
|
||||
from syscfg.models import *
|
||||
from common import generic
|
||||
|
||||
|
||||
class SiteForm(ModelForm):
|
||||
"""
|
||||
|
||||
"""
|
||||
class Meta:
|
||||
model = Site
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class SiteAdmin(admin.ModelAdmin):
|
||||
list_per_page = 10
|
||||
list_display = ['name', 'begin', 'end']
|
||||
fields = (('begin', 'end'), 'name', 'description', 'user')
|
||||
filter_horizontal = ['user']
|
||||
form = SiteForm
|
||||
|
||||
|
||||
class ModuleAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
CODE_PREFIX = 'U'
|
||||
list_display = ['code','name','parent','status']
|
||||
ordering = ['weight']
|
||||
raw_id_fields = ['parent']
|
||||
|
||||
|
||||
class MenuAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
CODE_PREFIX = 'M'
|
||||
|
||||
list_display = ['code','name','module','status']
|
||||
list_filter = ['module']
|
||||
ordering = ['weight']
|
||||
raw_id_fields = ['module']
|
||||
|
||||
|
||||
class RoleAdmin(generic.BOAdmin):
|
||||
CODE_NUMBER_WIDTH = 3
|
||||
CODE_PREFIX = 'R'
|
||||
list_display = ['code','name','status']
|
||||
filter_horizontal = ['users','menus']
|
||||
|
||||
|
||||
admin.site.register(Site, SiteAdmin)
|
||||
admin.site.register(Module,ModuleAdmin)
|
||||
admin.site.register(Menu,MenuAdmin)
|
||||
admin.site.register(Role,RoleAdmin)
|
||||
@@ -0,0 +1,9 @@
|
||||
__author__ = 'zhugl'
|
||||
# created at 15-4-22
|
||||
from django.apps.config import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class SysConfig(AppConfig):
|
||||
name = 'syscfg'
|
||||
verbose_name = _('SysConfig')
|
||||
@@ -0,0 +1,79 @@
|
||||
# coding=utf-8
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import const
|
||||
from common import generic
|
||||
|
||||
|
||||
class Site(models.Model):
|
||||
"""
|
||||
站点,一个站点下可有多个公司,处于同一个站点下的用户逻辑上位于同一个组织
|
||||
"""
|
||||
index_weight = 1
|
||||
begin = models.DateField(_('begin date'), blank=True,null=True)
|
||||
end = models.DateField(_('end date'), blank=True,null=True)
|
||||
name = models.CharField(_('site name'), max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_('site description'),blank=True,null=True)
|
||||
user = models.ManyToManyField(User,verbose_name=_('administrator'))
|
||||
|
||||
def __unicode__(self):
|
||||
return u'%s'%self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Site')
|
||||
verbose_name_plural = _('Site')
|
||||
|
||||
|
||||
class Module(generic.BO):
|
||||
"""
|
||||
模块管理
|
||||
"""
|
||||
index_weight = 2
|
||||
code = models.CharField(_("module code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("module name"),max_length=const.DB_CHAR_NAME_40)
|
||||
url = models.URLField(_("module url"),blank=True,null=True,max_length=const.DB_CHAR_NAME_80)
|
||||
weight = models.IntegerField(_("weight"),blank=True,null=True,default=99)
|
||||
icon = models.CharField(_("style class"),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
parent = models.ForeignKey('self',blank=True,null=True,verbose_name=_("parent"))
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("module")
|
||||
verbose_name_plural = _("module")
|
||||
|
||||
|
||||
class Menu(generic.BO):
|
||||
"""
|
||||
菜单管理
|
||||
"""
|
||||
index_weight = 3
|
||||
module = models.ForeignKey(Module,verbose_name=_("module"))
|
||||
code = models.CharField(_("menu code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("menu name"),max_length=const.DB_CHAR_NAME_40)
|
||||
url = models.URLField(_("menu url"),blank=True,null=True,max_length=const.DB_CHAR_NAME_80)
|
||||
weight = models.IntegerField(_("weight"),blank=True,null=True,default=99)
|
||||
icon = models.CharField(_("style class"),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("menu")
|
||||
verbose_name_plural = _("menu")
|
||||
|
||||
|
||||
class Role(generic.BO):
|
||||
"""
|
||||
角色管理,分配用户所拥有的菜单
|
||||
"""
|
||||
index_weight = 4
|
||||
code = models.CharField(_("role code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("role name"),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.CharField(_("description"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)
|
||||
status = models.BooleanField(_("in use"),default=True)
|
||||
parent = models.ForeignKey('self',blank=True,null=True,verbose_name=_("parent"))
|
||||
users = models.ManyToManyField(User,verbose_name=_("role users"),blank=True)
|
||||
menus = models.ManyToManyField(Menu,verbose_name=_("role menus"),blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("role")
|
||||
verbose_name_plural = _("role")
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends "admin/index.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ app_label }}{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
{% for app in app_lib %}
|
||||
| {% if app.is_current %} {{app.name}} {% else %}<a href="{{ app.app_url }}">{{ app.name }}</a> {% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block sidebar %}{% endblock %}
|
||||
@@ -0,0 +1,91 @@
|
||||
{% load i18n admin_static %}<!DOCTYPE html>
|
||||
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
|
||||
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
|
||||
<head>
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}" />
|
||||
{% block extrastyle %}{% endblock %}
|
||||
<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="{% block stylesheet_ie %}{% static "admin/css/ie.css" %}{% endblock %}" /><![endif]-->
|
||||
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}" />{% endif %}
|
||||
<script type="text/javascript">window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}";</script>
|
||||
<script type="text/javascript">window.__admin_utc_offset__ = "{% filter escapejs %}{% now "Z" %}{% endfilter %}";</script>
|
||||
{% block extrahead %}{% endblock %}
|
||||
{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
|
||||
</head>
|
||||
{% load i18n %}
|
||||
|
||||
<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}">
|
||||
|
||||
<!-- Container -->
|
||||
<div id="container">
|
||||
|
||||
{% if not is_popup %}
|
||||
<!-- Header -->
|
||||
<div id="header">
|
||||
<div id="branding">
|
||||
{% block branding %}{% endblock %}
|
||||
</div>
|
||||
{% block usertools %}
|
||||
{% if has_permission %}
|
||||
<div id="user-tools">
|
||||
{% block welcome-msg %}
|
||||
{% trans 'Welcome,' %}
|
||||
<strong>{% firstof user.get_short_name user.get_username %}</strong>.
|
||||
{% endblock %}
|
||||
{% block userlinks %}
|
||||
<a href="/admin/workflow/todolist">{% trans 'workflow todo' %}</a> /
|
||||
{% if site_url %}
|
||||
<a href="/admin/basedata/document">{% trans 'document' %}</a> /
|
||||
{% endif %}
|
||||
{% if user.is_active and user.is_staff %}
|
||||
{% url 'django-admindocs-docroot' as docsroot %}
|
||||
{% if docsroot %}
|
||||
<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> /
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if user.has_usable_password %}
|
||||
<a href="{% url 'admin:password_change' %}">{% trans 'Change password' %}</a> /
|
||||
{% endif %}
|
||||
<a href="{% url 'admin:logout' %}">{% trans 'Log out' %}</a>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block nav-global %}{% endblock %}
|
||||
</div>
|
||||
<!-- END Header -->
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
{% if title %} › {{ title }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block messages %}
|
||||
{% if messages %}
|
||||
<ul class="messagelist">{% for message in messages %}
|
||||
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
|
||||
{% endfor %}</ul>
|
||||
{% endif %}
|
||||
{% endblock messages %}
|
||||
|
||||
<!-- Content -->
|
||||
<div id="content" class="{% block coltype %}colM{% endblock %}">
|
||||
{% block pretitle %}{% endblock %}
|
||||
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
|
||||
{% block content %}
|
||||
{% block object-tools %}{% endblock %}
|
||||
{{ content }}
|
||||
{% endblock %}
|
||||
{% block sidebar %}{% endblock %}
|
||||
<br class="clear" />
|
||||
</div>
|
||||
<!-- END Content -->
|
||||
|
||||
{% block footer %}<div id="footer"></div>{% endblock %}
|
||||
</div>
|
||||
<!-- END Container -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,148 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
|
||||
{% block coltype %}colM{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
|
||||
› {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}<div id="content-main">
|
||||
{% block object-tools %}
|
||||
{% if change %}{% if not is_popup %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li>
|
||||
{% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
|
||||
</li>
|
||||
{% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
||||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
|
||||
{% if show_workflow_line%}
|
||||
<fieldset class="module aligned workflow">
|
||||
<h2>{% trans "workflow approve" %}</h2>
|
||||
<div style="padding:10px">
|
||||
{% if can_restart %}
|
||||
<a class="button" href="restart/{{workflow_instance.id}}" id="workflow_restart">{% trans "restart workflow" %}</a>
|
||||
<p style="float:right;color:#666">{% trans "your apply has been denied,you can restart a new apply" %}</p>
|
||||
{% else %}
|
||||
<label class="control"><input type="radio" name="operation" value="1" checked> {% trans "agree" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="3"> {% trans "deny" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="4"> {% trans "terminate" %}</label>
|
||||
<a class="button" href="approve/1" id="workflow_approve">{% trans "submit" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
|
||||
</p>
|
||||
{{ adminform.form.non_field_errors }}
|
||||
{% endif %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
{% include "admin/includes/fieldset.html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
|
||||
{% block inline_field_sets %}
|
||||
{% for inline_admin_formset in inline_admin_formsets %}
|
||||
{% include inline_admin_formset.opts.template %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_related_objects %}{% endblock %}
|
||||
|
||||
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
|
||||
|
||||
{% block admin_change_form_document_ready %}
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$('.add-another').click(function(e) {
|
||||
e.preventDefault();
|
||||
showAddAnotherPopup(this);
|
||||
});
|
||||
$('.related-lookup').click(function(e) {
|
||||
e.preventDefault();
|
||||
showRelatedObjectLookupPopup(this);
|
||||
});
|
||||
|
||||
{% if adminform and add %}
|
||||
$('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus()
|
||||
{% endif %}
|
||||
{% if workflow_modal %}
|
||||
{% if workflow_instance %}
|
||||
workflow_modal = "{{ workflow_modal.code }}";
|
||||
workflow_instance = "{{ workflow_instance.code }}";
|
||||
$('tr.add-row').hide();
|
||||
{% if can_edit %}
|
||||
$('a.deletelink').hide();
|
||||
$("#workflow_submit").hide();
|
||||
$("input[name='_addanother']").hide();
|
||||
$("input[name='_continue']").hide();
|
||||
{% else %}
|
||||
$('input,select,textarea').attr('disabled','true');
|
||||
$('div.submit-row').hide();
|
||||
$('.workflow input,.workflow select').removeAttr("disabled");
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% if extra_buttons %}
|
||||
{% for button in extra_buttons %}
|
||||
$("<a href='{{button.href}}' class='button'>{{button.title}}</a>").insertAfter("#workflow_submit");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if readonly %}
|
||||
$('input,select,textarea').attr('disabled',true);
|
||||
$('div.submit-row').hide();
|
||||
$('tr.add-row').hide();
|
||||
{% endif %}
|
||||
try{
|
||||
$("div.inline-group table tbody tr.form-row").removeClass('has_original');
|
||||
$("div.inline-group table tbody tr.form-row td:first-child").find('p').hide();
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
});
|
||||
})(django.jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{# JavaScript for prepopulated fields #}
|
||||
{% prepopulated_fields_js %}
|
||||
|
||||
</div>
|
||||
</form></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,110 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_static %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block coltype %}colMS{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
{% for app in maxi_app_list %}
|
||||
|
||||
| <a href="{{ app.app_url }}">{{ app.name }}</a>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
{% if maxi_app_list %}
|
||||
{% for app in maxi_app_list %}
|
||||
|
||||
<div class="app-{{ app.app_label }} module">
|
||||
<table>
|
||||
<caption>
|
||||
<a href="{{ app.app_url }}" class="section" title="{% blocktrans with name=app.name %}Models in the {{ name }} application{% endblocktrans %}">{{ app.name }}</a>
|
||||
</caption>
|
||||
{% for model in app.models %}
|
||||
<tr class="model-{{ model.object_name|lower }}">
|
||||
{% if model.admin_url %}
|
||||
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
|
||||
{% else %}
|
||||
<th scope="row">{{ model.name }}</th>
|
||||
{% endif %}
|
||||
|
||||
{% if model.add_url %}
|
||||
<td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td>
|
||||
{% else %}
|
||||
<td> </td>
|
||||
{% endif %}
|
||||
|
||||
{% if model.admin_url %}
|
||||
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
|
||||
{% else %}
|
||||
<td> </td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>{% trans "You don't have permission to edit anything." %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
<div id="content-related" style="width:18em">
|
||||
<div class="module">
|
||||
<h2><a href="workflow/todolist" style="float:right">更多</a>我的待办</h2>
|
||||
{% if not todolist %}
|
||||
<p>无待办任务</p>
|
||||
{% else %}
|
||||
<ul class="actionlist">
|
||||
{% for todo in todolist%}
|
||||
<li class="changelink">
|
||||
{{todo.href}}<br/>
|
||||
<span class="mini quiet">{{todo.submitter}} {{todo.start_time}}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="module" id="recent-actions-module">
|
||||
<h2>{% trans 'Recent Actions' %}</h2>
|
||||
<h3>{% trans 'My Actions' %}</h3>
|
||||
{% load log %}
|
||||
{% get_admin_log 10 as admin_log for_user user %}
|
||||
{% if not admin_log %}
|
||||
<p>{% trans 'None available' %}</p>
|
||||
{% else %}
|
||||
<ul class="actionlist">
|
||||
{% for entry in admin_log %}
|
||||
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
|
||||
{% if entry.is_deletion or not entry.get_admin_url %}
|
||||
{{ entry.object_repr }}
|
||||
{% else %}
|
||||
<a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
|
||||
{% endif %}
|
||||
<br/>
|
||||
{% if entry.content_type %}
|
||||
<span class="mini quiet">{% filter capfirst %}{{ entry.content_type }}{% endfilter %}</span>
|
||||
{% else %}
|
||||
<span class="mini quiet">{% trans 'Unknown content' %}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,167 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
|
||||
{% block coltype %}colM{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
|
||||
› {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}<div id="content-main">
|
||||
{% block object-tools %}
|
||||
{% if change %}{% if not is_popup %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li>
|
||||
{% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
|
||||
</li>
|
||||
{% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
||||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
|
||||
{% if show_workflow_line%}
|
||||
<fieldset class="module aligned workflow">
|
||||
<h2>{% trans "workflow approve" %}</h2>
|
||||
<div style="padding:10px">
|
||||
{% if can_restart %}
|
||||
<a class="button" href="restart/{{workflow_instance.id}}" id="workflow_restart">{% trans "restart workflow" %}</a>
|
||||
<p style="float:right;color:#666">{% trans "your apply has been denied,you can restart a new apply" %}</p>
|
||||
{% else %}
|
||||
<label class="control"><input type="radio" name="operation" value="1" checked> {% trans "agree" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="3"> {% trans "deny" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="4"> {% trans "terminate" %}</label>
|
||||
<a class="button" href="approve/1" id="workflow_submit">{% trans "submit" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
|
||||
</p>
|
||||
{{ adminform.form.non_field_errors }}
|
||||
{% endif %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
{% include "admin/includes/fieldset.html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
|
||||
{% block inline_field_sets %}
|
||||
{% for inline_admin_formset in inline_admin_formsets %}
|
||||
{% include inline_admin_formset.opts.template %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_related_objects %}{% endblock %}
|
||||
|
||||
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
|
||||
|
||||
{% block admin_change_form_document_ready %}
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$('.add-another').click(function(e) {
|
||||
e.preventDefault();
|
||||
showAddAnotherPopup(this);
|
||||
});
|
||||
$('.related-lookup').click(function(e) {
|
||||
e.preventDefault();
|
||||
showRelatedObjectLookupPopup(this);
|
||||
});
|
||||
|
||||
{% if adminform and add %}
|
||||
$('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus()
|
||||
{% endif %}
|
||||
{% if workflow_modal %}
|
||||
{% if workflow_instance %}
|
||||
workflow_modal = "{{ workflow_modal.code }}";
|
||||
workflow_instance = "{{ workflow_instance.code }}";
|
||||
$('tr.add-row').hide();
|
||||
$('input,select,textarea').attr('disabled','true');
|
||||
$('div.submit-row').hide();
|
||||
$('.workflow input,.workflow select').removeAttr("disabled");
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% else %}
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% if extra_buttons %}
|
||||
{% for button in extra_buttons %}
|
||||
$("<a href='{{button.href}}' class='button'>{{button.title}}</a>").insertAfter("#workflow_submit");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if readonly %}
|
||||
$('input,select,textarea').attr('disabled',true);
|
||||
$('div.submit-row').hide();
|
||||
$('tr.add-row').hide();
|
||||
{% endif %}
|
||||
});
|
||||
})(django.jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{# JavaScript for prepopulated fields #}
|
||||
{% prepopulated_fields_js %}
|
||||
|
||||
</div>
|
||||
</form></div>
|
||||
{% if detail %}
|
||||
<h1 style="margin-top:15px">{% trans "InOut History" %}</h1>
|
||||
<div class="module">
|
||||
<table id="workflow-history">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{% trans 'execute time' %}</th>
|
||||
<th scope="col">{% trans 'plus or minus prop' %}</th>
|
||||
<th scope="col">{% trans 'price' %}</th>
|
||||
<th scope="col">{% trans 'count' %}</th>
|
||||
<th scope="col">{% trans 'measure' %}</th>
|
||||
<th scope="col">{% trans 'status' %}</th>
|
||||
<th scope="col">{% trans 'source' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in detail %}
|
||||
<tr>
|
||||
<th scope="row">{{ item.event_time|date:"DATETIME_FORMAT" }}</th>
|
||||
<td class="col">{{ item.prop }}</td>
|
||||
<td class="col">{{ item.price }}</td>
|
||||
<td class="col">{{ item.cnt }}</td>
|
||||
<td class="col">{{ item.measure }}</td>
|
||||
<td class="col">{% if item.status %} {% trans 'EXECUTED'%} {% endif %}</td>
|
||||
<td class="col">{{ item.source }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,136 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
|
||||
{% block coltype %}colM{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
|
||||
› {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}<div id="content-main">
|
||||
{% block object-tools %}
|
||||
{% if change %}{% if not is_popup %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li>
|
||||
{% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
|
||||
</li>
|
||||
{% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
||||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
|
||||
{% if show_workflow_line%}
|
||||
<fieldset class="module aligned workflow">
|
||||
<h2>{% trans "workflow approve" %}</h2>
|
||||
<div style="padding:10px">
|
||||
{% if can_restart %}
|
||||
<a class="button" href="restart/{{workflow_instance.id}}" id="workflow_restart">{% trans "restart workflow" %}</a>
|
||||
<p style="float:right;color:#666">{% trans "your apply has been denied,you can restart a new apply" %}</p>
|
||||
{% else %}
|
||||
<label class="control"><input type="radio" name="operation" value="1" checked> {% trans "agree" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="3"> {% trans "deny" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="4"> {% trans "terminate" %}</label>
|
||||
<a class="button" href="approve/1" id="workflow_submit">{% trans "submit" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
|
||||
</p>
|
||||
{{ adminform.form.non_field_errors }}
|
||||
{% endif %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
{% include "admin/includes/fieldset.html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
|
||||
{% block inline_field_sets %}
|
||||
{% for inline_admin_formset in inline_admin_formsets %}
|
||||
{% include inline_admin_formset.opts.template %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_related_objects %}{% endblock %}
|
||||
|
||||
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
|
||||
|
||||
{% block admin_change_form_document_ready %}
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$('.add-another').click(function(e) {
|
||||
e.preventDefault();
|
||||
showAddAnotherPopup(this);
|
||||
});
|
||||
$('.related-lookup').click(function(e) {
|
||||
e.preventDefault();
|
||||
showRelatedObjectLookupPopup(this);
|
||||
});
|
||||
$("div.inline-group tr").removeClass("has_original");
|
||||
$("td.original p").hide();
|
||||
{% if adminform and add %}
|
||||
$('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus()
|
||||
{% endif %}
|
||||
{% if workflow_modal %}
|
||||
{% if workflow_instance %}
|
||||
workflow_modal = "{{ workflow_modal.code }}";
|
||||
workflow_instance = "{{ workflow_instance.code }}";
|
||||
$('tr.add-row').hide();
|
||||
$('input,select').attr('disabled','true');
|
||||
$('div.submit-row').hide();
|
||||
$('.workflow input,.workflow select').removeAttr("disabled");
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% else %}
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% if extra_buttons %}
|
||||
{% for button in extra_buttons %}
|
||||
$("<a href='{{button.href}}' class='button'>{{button.title}}</a>").insertAfter("#workflow_submit");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if readonly %}
|
||||
$('input,select').attr('disabled',true);
|
||||
$('div.submit-row').hide();
|
||||
$('tr.add-row').hide();
|
||||
{% endif %}
|
||||
});
|
||||
})(django.jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{# JavaScript for prepopulated fields #}
|
||||
{% prepopulated_fields_js %}
|
||||
|
||||
</div>
|
||||
</form></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% if action_name %}{{action_name}} {% else %} {% trans 'action' %}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p> {% trans 'Are your sure to execute the operations?' %} </p>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<div>
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,137 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
|
||||
{% block coltype %}colM{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
|
||||
› {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}<div id="content-main">
|
||||
{% block object-tools %}
|
||||
{% if change %}{% if not is_popup %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li>
|
||||
{% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
|
||||
</li>
|
||||
{% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
||||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
|
||||
{% if show_workflow_line%}
|
||||
<fieldset class="module aligned workflow">
|
||||
<h2>{% trans "workflow approve" %}</h2>
|
||||
<div style="padding:10px">
|
||||
{% if can_restart %}
|
||||
<a class="button" href="restart/{{workflow_instance.id}}" id="workflow_restart">{% trans "restart workflow" %}</a>
|
||||
<p style="float:right;color:#666">{% trans "your apply has been denied,you can restart a new apply" %}</p>
|
||||
{% else %}
|
||||
<label class="control"><input type="radio" name="operation" value="1" checked> {% trans "agree" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="3"> {% trans "deny" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="4"> {% trans "terminate" %}</label>
|
||||
<a class="button" href="approve/1" id="workflow_submit">{% trans "submit" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
|
||||
</p>
|
||||
{{ adminform.form.non_field_errors }}
|
||||
{% endif %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
{% include "admin/includes/fieldset.html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
|
||||
{% block inline_field_sets %}
|
||||
{% for inline_admin_formset in inline_admin_formsets %}
|
||||
{% include inline_admin_formset.opts.template %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_related_objects %}{% endblock %}
|
||||
|
||||
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
|
||||
|
||||
{% block admin_change_form_document_ready %}
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$('.add-another').click(function(e) {
|
||||
e.preventDefault();
|
||||
showAddAnotherPopup(this);
|
||||
});
|
||||
$('.related-lookup').click(function(e) {
|
||||
e.preventDefault();
|
||||
showRelatedObjectLookupPopup(this);
|
||||
});
|
||||
$("div.inline-group tr").removeClass("has_original");
|
||||
$("td.original p").hide();
|
||||
{% if adminform and add %}
|
||||
$('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus()
|
||||
{% endif %}
|
||||
{% if workflow_modal %}
|
||||
{% if workflow_instance %}
|
||||
workflow_modal = "{{ workflow_modal.code }}";
|
||||
workflow_instance = "{{ workflow_instance.code }}";
|
||||
$('tr.add-row').hide();
|
||||
$('input,select,textarea').attr('disabled','true');
|
||||
$('div.submit-row').hide();
|
||||
$('.workflow input,.workflow select').removeAttr("disabled");
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% else %}
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% if extra_buttons %}
|
||||
{% for button in extra_buttons %}
|
||||
$("<a href='{{button.href}}' class='button'>{{button.title}}</a>").insertAfter("#workflow_submit");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if readonly %}
|
||||
$('input,select,textarea').attr('disabled',true);
|
||||
$('div.submit-row').hide();
|
||||
$('tr.add-row').hide();
|
||||
{% endif %}
|
||||
$('div.inline-group select').attr('disabled',true);
|
||||
});
|
||||
})(django.jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{# JavaScript for prepopulated fields #}
|
||||
{% prepopulated_fields_js %}
|
||||
|
||||
</div>
|
||||
</form></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% trans 'action' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p> {% trans 'Are your sure to execute the check out operations?' %} </p>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<div>
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,82 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls %}
|
||||
{% block extrastyle %}
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/maximus.css" />
|
||||
{% endblock %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ module_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% trans 'History' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="content-main">
|
||||
<div class="module">
|
||||
|
||||
{% if action_list %}
|
||||
<table id="change-history">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{% trans 'Date/time' %}</th>
|
||||
<th scope="col">{% trans 'User' %}</th>
|
||||
<th scope="col">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for action in action_list %}
|
||||
<tr>
|
||||
<th scope="row">{{ action.action_time|date:"DATETIME_FORMAT" }}</th>
|
||||
<td>{{ action.user.get_username }}{% if action.user.get_full_name %} ({{ action.user.get_full_name }}){% endif %}</td>
|
||||
<td>{{ action.change_message }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p>{% trans "This object doesn't have a change history. It probably wasn't added via this admin site." %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if history_list %}
|
||||
<h1 style="margin-top:15px">{% trans "Workflow History" %}</h1>
|
||||
<div class="module">
|
||||
<table id="workflow-history">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{% trans 'Date/time' %}</th>
|
||||
<th scope="col">{% trans 'User' %}</th>
|
||||
<th scope="col">{% trans 'node' %}</th>
|
||||
<th scope="col">{% trans 'Action' %}</th>
|
||||
<th scope="col">{% trans 'Workflow Memo' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for history in history_list %}
|
||||
<tr>
|
||||
<th scope="row">{{ history.pro_time|date:"DATETIME_FORMAT" }}</th>
|
||||
<td class="col">{{ history.user.get_username }}{% if history.user.get_full_name %} ({{ history.user.get_full_name }}){% endif %}</td>
|
||||
<td class="col">{{ history.get_node_desc }}</td>
|
||||
<td class="col">{{ history.get_action_desc }}</td>
|
||||
<td>{{ history.get_memo_desc }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if todo_list %}
|
||||
{% for todo in todo_list %}
|
||||
<tr>
|
||||
<th scope="row">{% if todo.is_read %}{{ todo.read_time|date:"DATETIME_FORMAT" }}{% endif %}</th>
|
||||
<td class="col">{{ todo.user.get_username }}{% if todo.user.get_full_name %} ({{ todo.user.get_full_name }}){% endif %}</td>
|
||||
<td class="col">{{ todo.node.name }}</td>
|
||||
<td class="col">{% if todo.is_read %} {% trans 'already read' %} {% else %} {% trans 'unread' %} {% endif %}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,173 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
|
||||
{% block coltype %}colM{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
|
||||
› {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}<div id="content-main">
|
||||
{% block object-tools %}
|
||||
{% if change %}{% if not is_popup %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li>
|
||||
{% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
|
||||
</li>
|
||||
{% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
||||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
|
||||
{% if show_workflow_line%}
|
||||
<fieldset class="module aligned workflow">
|
||||
<h2>{% trans "workflow approve" %}</h2>
|
||||
<div style="padding:10px">
|
||||
{% if can_restart %}
|
||||
<a class="button" href="restart/{{workflow_instance.id}}" id="workflow_restart">{% trans "restart workflow" %}</a>
|
||||
<p style="float:right;color:#666">{% trans "your apply has been denied,you can restart a new apply" %}</p>
|
||||
{% else %}
|
||||
<label class="control"><input type="radio" name="operation" value="1" checked> {% trans "agree" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="3"> {% trans "deny" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="4"> {% trans "terminate" %}</label>
|
||||
<a class="button" href="approve/1" id="workflow_approve">{% trans "submit" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
|
||||
</p>
|
||||
{{ adminform.form.non_field_errors }}
|
||||
{% endif %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
{% include "admin/includes/fieldset.html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
|
||||
{% block inline_field_sets %}
|
||||
{% for inline_admin_formset in inline_admin_formsets %}
|
||||
{% include inline_admin_formset.opts.template %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_related_objects %}{% endblock %}
|
||||
|
||||
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
|
||||
|
||||
{% block admin_change_form_document_ready %}
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$('.add-another').click(function(e) {
|
||||
e.preventDefault();
|
||||
showAddAnotherPopup(this);
|
||||
});
|
||||
$('.related-lookup').click(function(e) {
|
||||
e.preventDefault();
|
||||
showRelatedObjectLookupPopup(this);
|
||||
});
|
||||
|
||||
{% if adminform and add %}
|
||||
$('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus()
|
||||
{% endif %}
|
||||
{% if workflow_modal %}
|
||||
{% if workflow_instance %}
|
||||
workflow_modal = "{{ workflow_modal.code }}";
|
||||
workflow_instance = "{{ workflow_instance.code }}";
|
||||
$('tr.add-row').hide();
|
||||
{% if can_edit %}
|
||||
$('a.deletelink').hide();
|
||||
$("#workflow_submit").hide();
|
||||
$("input[name='_addanother']").hide();
|
||||
$("input[name='_continue']").hide();
|
||||
{% else %}
|
||||
$('input,select,textarea').attr('disabled','true');
|
||||
$('div.submit-row').hide();
|
||||
$('.workflow input,.workflow select').removeAttr("disabled");
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% if extra_buttons %}
|
||||
{% for button in extra_buttons %}
|
||||
$("<a href='{{button.href}}' class='button'>{{button.title}}</a>").insertAfter("#workflow_submit");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if readonly %}
|
||||
$('input,select,textarea').attr('disabled',true);
|
||||
$('div.submit-row').hide();
|
||||
$('tr.add-row').hide();
|
||||
{% endif %}
|
||||
try{
|
||||
$("div.inline-group table tbody tr.form-row").removeClass('has_original');
|
||||
$("div.inline-group table tbody tr.form-row td:first-child").find('p').hide();
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
});
|
||||
$('#id_classification').bind('change',function(){
|
||||
var c = $("select[name='classification'] option:selected").val();
|
||||
//alert(c);
|
||||
if(c=='R' || c=='Q'){
|
||||
$("label[for='id_service']").removeClass('required');
|
||||
$('#woitem_set-group').hide();
|
||||
$('#woextravalue_set-group').hide();
|
||||
$('div.field-service').hide();
|
||||
$('div.field-detail').hide();
|
||||
}else{
|
||||
$('#woitem_set-group').show();
|
||||
$('#woextravalue_set-group').show();
|
||||
$('div.field-service').show();
|
||||
if(c=='D'){
|
||||
$("label[for='id_service']").removeClass('required');
|
||||
$('div.field-detail').show();
|
||||
}
|
||||
if(c=='S'){
|
||||
$('div.field-detail').hide();
|
||||
$("label[for='id_service']").addClass('required');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#woextravalue_set-group').hide();
|
||||
})(django.jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{# JavaScript for prepopulated fields #}
|
||||
{% prepopulated_fields_js %}
|
||||
|
||||
</div>
|
||||
</form></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,18 @@
|
||||
{% load i18n admin_urls %}
|
||||
<div class="submit-row">
|
||||
|
||||
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
|
||||
<a href="start" class="button" id="workflow_submit">{% trans "submit" %}</a>
|
||||
{% for button in extra_buttons %}
|
||||
<a href="{{button.href}}" class="button">{{button.title}}</a>
|
||||
{% endfor %}
|
||||
{{extra_buttons}}
|
||||
{% if show_delete_link %}
|
||||
{% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
|
||||
<p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">{% trans "Delete" %}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{% endif %}
|
||||
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
|
||||
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,164 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls admin_static admin_modify %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
|
||||
{% block coltype %}colM{% endblock %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
|
||||
|
||||
{% if not is_popup %}
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
|
||||
› {% if add %}{% trans 'Add' %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18" }}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block content %}<div id="content-main">
|
||||
{% block object-tools %}
|
||||
{% if change %}{% if not is_popup %}
|
||||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li>
|
||||
{% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
|
||||
<a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
|
||||
</li>
|
||||
{% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
|
||||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
|
||||
{% if show_workflow_line%}
|
||||
<fieldset class="module aligned workflow">
|
||||
<h2>{% trans "workflow approve" %}</h2>
|
||||
<div style="padding:10px">
|
||||
{% if can_restart %}
|
||||
<a class="button" href="restart/{{workflow_instance.id}}" id="workflow_restart">{% trans "restart workflow" %}</a>
|
||||
<p style="float:right;color:#666">{% trans "your apply has been denied,you can restart a new apply" %}</p>
|
||||
{% else %}
|
||||
<label class="control"><input type="radio" name="operation" value="1" checked> {% trans "agree" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="3"> {% trans "deny" %}</label>
|
||||
<label class="control"><input type="radio" name="operation" value="4"> {% trans "terminate" %}</label>
|
||||
<a class="button" href="approve/1" id="workflow_approve">{% trans "submit" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
{% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
|
||||
</p>
|
||||
{{ adminform.form.non_field_errors }}
|
||||
{% endif %}
|
||||
|
||||
{% block field_sets %}
|
||||
{% for fieldset in adminform %}
|
||||
{% include "admin/includes/fieldset.html" %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_field_sets %}{% endblock %}
|
||||
|
||||
{% block inline_field_sets %}
|
||||
{% for inline_admin_formset in inline_admin_formsets %}
|
||||
{% include inline_admin_formset.opts.template %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block after_related_objects %}{% endblock %}
|
||||
|
||||
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
|
||||
|
||||
{% block admin_change_form_document_ready %}
|
||||
<script type="text/javascript">
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$('.add-another').click(function(e) {
|
||||
e.preventDefault();
|
||||
showAddAnotherPopup(this);
|
||||
});
|
||||
$('.related-lookup').click(function(e) {
|
||||
e.preventDefault();
|
||||
showRelatedObjectLookupPopup(this);
|
||||
});
|
||||
|
||||
{% if adminform and add %}
|
||||
$('form#{{ opts.model_name }}_form :input:visible:enabled:first').focus()
|
||||
{% endif %}
|
||||
{% if workflow_modal %}
|
||||
{% if workflow_instance %}
|
||||
workflow_modal = "{{ workflow_modal.code }}";
|
||||
workflow_instance = "{{ workflow_instance.code }}";
|
||||
$('tr.add-row').hide();
|
||||
$('input,select,textarea').attr('disabled','true');
|
||||
$('div.submit-row').hide();
|
||||
$('.workflow input,.workflow select').removeAttr("disabled");
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% else %}
|
||||
$("#workflow_submit").hide();
|
||||
{% endif %}
|
||||
{% if extra_buttons %}
|
||||
{% for button in extra_buttons %}
|
||||
$("<a href='{{button.href}}' class='button'>{{button.title}}</a>").insertAfter("#workflow_submit");
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if readonly %}
|
||||
$('input,select,textarea').attr('disabled',true);
|
||||
$('div.submit-row').hide();
|
||||
$('tr.add-row').hide();
|
||||
{% endif %}
|
||||
try{
|
||||
$("div.inline-group table tbody tr.form-row").removeClass('has_original');
|
||||
$("div.inline-group table tbody tr.form-row td:first-child").find('p').hide();
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
});
|
||||
$("input[name='handler_type']").bind('click',function(){
|
||||
v = $("input[name='handler_type']:checked").val();
|
||||
if(v==1){
|
||||
$('div.field-users').show();
|
||||
$('div.field-positions').hide();
|
||||
$('div.field-roles').hide();
|
||||
}else if(v==2){
|
||||
$('div.field-users').hide();
|
||||
$('div.field-positions').show();
|
||||
$('div.field-roles').hide();
|
||||
}else if(v==3){
|
||||
$('div.field-users').hide();
|
||||
$('div.field-positions').hide();
|
||||
$('div.field-roles').show();
|
||||
}else if(v==4){
|
||||
$('div.field-users').hide();
|
||||
$('div.field-positions').hide();
|
||||
$('div.field-roles').hide();
|
||||
}
|
||||
});
|
||||
$('div.field-users').show();
|
||||
$('div.field-positions').hide();
|
||||
$('div.field-roles').hide();
|
||||
})(django.jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{# JavaScript for prepopulated fields #}
|
||||
{% prepopulated_fields_js %}
|
||||
|
||||
</div>
|
||||
</form></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,67 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls %}
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="/static/css/maximus.css" />{% endblock %}
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% trans 'workflow approve' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if operation == '4' %}
|
||||
<p>{% trans "Are you sure to terminate the request?" %}</p>
|
||||
{% elif operation == '3' %}
|
||||
<p>{% trans "Are you sure to deny the request?" %}</p>
|
||||
{% else %}
|
||||
<p>{% blocktrans with escaped_object=object %}Are you sure you want to submit the {{ object_name }} "{{ escaped_object }}"? {% endblocktrans %}</p>
|
||||
{% endif%}
|
||||
<h3> {{ workflow_modal.code }} {{ workflow_modal.name }} </h3>
|
||||
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
{% if is_stop_node %}
|
||||
<p> {% trans "current node is stop node,click the submit button to complete it" %} </p>
|
||||
{% else %}
|
||||
{% for node_user in node_users %}
|
||||
{% if node_user.node == 'start'%}
|
||||
<p class="next-node">{% trans "back to start node" %}</p>
|
||||
{%else%}
|
||||
<p class="next-node">{% trans "next node" %}:{{ node_user.node.name }}</p>
|
||||
{% endif%}
|
||||
{% if next_node_description %}
|
||||
<p class="tooltip">{% trans "attention" %}:{{next_node_description}}</p>
|
||||
{% endif %}
|
||||
{% if node_has_users %}
|
||||
<ul class="node-users">
|
||||
{% for user in node_user.users %}
|
||||
<li><input type="checkbox" name="{{checkbox_name}}" value="{{user.id}}" checked> {{user.last_name}}{{user.first_name}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{% trans "No user was configured to handle this node"%}</p>
|
||||
{% endif %}
|
||||
{% endfor%}
|
||||
{% endif%}
|
||||
{% if is_stop_node or node_has_users%}
|
||||
<label style="display:block">{% trans "Workflow Memo" %}:</label>
|
||||
<textarea name="memo" rows="3" cols="80"></textarea>
|
||||
<div class="workflow_approve_command">
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
<input type="hidden" name="oper_type" value="{{operation}}" />
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n admin_urls %}
|
||||
|
||||
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<div class="breadcrumbs">
|
||||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% trans 'submit' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if has_workflow %}
|
||||
<p>{% blocktrans with escaped_object=object %}Are you sure you want to submit the {{ object_name }} "{{ escaped_object }}"? {% endblocktrans %}</p>
|
||||
<h3> {{ workflow_modal.code }} {{ workflow_modal.name }} </h3>
|
||||
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
{% if next_node %}
|
||||
<p class="next-node">{% trans "next node" %}:{{ next_node.name }}</p>
|
||||
{% if has_next_user %}
|
||||
<ul class="node-users">
|
||||
{% for user in next_users %}
|
||||
<li><input type="checkbox" name="{{checkbox_name}}" value="{{user.id}}" checked> {{user.last_name}}{{user.first_name}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{% trans "No user was configured to handle this node"%}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div>
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "No, take me back" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{% trans "you needs to config a workflow model for this content type" %}</p>
|
||||
<a href="#" onclick="window.history.back(); return false;" class="button cancel-link">{% trans "OK" %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user