Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
7e16fa6804
1543
inventory/management/commands/claude.py
Normal file
1543
inventory/management/commands/claude.py
Normal file
File diff suppressed because it is too large
Load Diff
124
inventory/management/commands/deepseek.py
Normal file
124
inventory/management/commands/deepseek.py
Normal file
@ -0,0 +1,124 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django_ledger.models import EntityModel, ChartOfAccountModel, AccountModel
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Creates Chart of Accounts for Deepseek entity'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# Get or create admin user
|
||||
admin_user = User.objects.filter(is_superuser=True).first()
|
||||
if not admin_user:
|
||||
self.stdout.write(self.style.ERROR('No admin user found!'))
|
||||
return
|
||||
|
||||
# Get or create Deepseek entity with minimal valid fields
|
||||
entity, created = EntityModel.objects.get_or_create(
|
||||
name='Deepseek',
|
||||
defaults={
|
||||
'admin': admin_user,
|
||||
'fy_start_month': 1, # January fiscal year start
|
||||
'accrual_method': True # Using accrual accounting
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
self.stdout.write(self.style.SUCCESS('Created Deepseek entity'))
|
||||
else:
|
||||
self.stdout.write(self.style.SUCCESS('Deepseek entity already exists'))
|
||||
|
||||
# Get or create Chart of Accounts
|
||||
coa, created = ChartOfAccountModel.objects.get_or_create(
|
||||
slug='deepseek-coa',
|
||||
defaults={
|
||||
'name': 'Deepseek Chart of Accounts',
|
||||
'entity': entity,
|
||||
'description': 'Standard COA for Deepseek automotive business'
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
self.stdout.write(self.style.SUCCESS('Created Chart of Accounts'))
|
||||
else:
|
||||
self.stdout.write(self.style.SUCCESS('Chart of Accounts already exists'))
|
||||
|
||||
# Account definitions with string role literals
|
||||
ACCOUNTS = [
|
||||
# Assets
|
||||
('1010', 'Cash on Hand', 'الصندوق', 'asset_ca_cash'),
|
||||
('1020', 'Bank', 'البنك', 'asset_ca_cash'),
|
||||
('1030', 'Accounts Receivable', 'العملاء', 'asset_ca_receivable'),
|
||||
('1040', 'Inventory (Cars)', 'مخزون السيارات', 'asset_ca_inventory'),
|
||||
('1045', 'Spare Parts Inventory', 'مخزون قطع الغيار', 'asset_ca_inventory'),
|
||||
('1050', 'Employee Advances', 'سُلف وأمانات الموظفين', 'asset_ca_other'),
|
||||
('1060', 'Prepaid Expenses', 'مصروفات مدفوعة مقدماً', 'asset_ca_other'),
|
||||
('1070', 'Notes Receivable', 'أوراق القبض', 'asset_ca_receivable'),
|
||||
('2010', 'Lands', 'أراضي', 'asset_ppe_land'),
|
||||
('2011', 'Buildings', 'مباني', 'asset_ppe_building'),
|
||||
('2012', 'Company Vehicles', 'سيارات الشركة', 'asset_ppe_equipment'),
|
||||
('2013', 'Equipment & Tools', 'أجهزة ومعدات', 'asset_ppe_equipment'),
|
||||
('2014', 'Furniture & Fixtures', 'أثاث وديكور', 'asset_ppe_equipment'),
|
||||
('2015', 'Other Fixed Assets', 'أصول ثابتة أخرى', 'asset_ppe_other'),
|
||||
('2020', 'Long-term Investments', 'استثمارات طويلة الأجل', 'asset_lt_investments'),
|
||||
('2030', 'Intangible Assets', 'أصول غير ملموسة', 'asset_lt_intangible'),
|
||||
|
||||
# Liabilities
|
||||
('3010', 'Accounts Payable', 'الموردين', 'liability_cl_acc_payable'),
|
||||
('3020', 'Notes Payable', 'أوراق الدفع', 'liability_cl_acc_payable'),
|
||||
('3030', 'Short-term Loans', 'قروض قصيرة الأجل', 'liability_cl_debt'),
|
||||
('3040', 'Employee Payables', 'السلف المستحقة', 'liability_cl_acc_payable'),
|
||||
('3050', 'Accrued Expenses', 'مصروفات مستحقة', 'liability_cl_acc_expense'),
|
||||
('3060', 'Accrued Taxes', 'ضرائب مستحقة', 'liability_cl_acc_expense'),
|
||||
('3070', 'Provisions', 'مخصصات', 'liability_cl_acc_expense'),
|
||||
('4010', 'Long-term Bank Loans', 'قروض طويلة الأجل', 'liability_lt_loans'),
|
||||
('4020', 'Lease Liabilities', 'التزامات تمويلية', 'liability_lt_loans'),
|
||||
('4030', 'Other Long-term Liabilities', 'التزامات أخرى طويلة الأجل', 'liability_lt_other'),
|
||||
|
||||
# Equity
|
||||
('5010', 'Capital', 'رأس المال', 'equity_capital'),
|
||||
('5020', 'Statutory Reserve', 'الاحتياطي القانوني', 'equity_retained'),
|
||||
('5030', 'Retained Earnings', 'احتياطي الأرباح', 'equity_retained'),
|
||||
('5040', 'Profit & Loss for the Period', 'أرباح وخسائر الفترة', 'equity_earnings'),
|
||||
|
||||
# Income
|
||||
('6010', 'Car Sales', 'مبيعات السيارات', 'income_operating'),
|
||||
('6020', 'After-Sales Services', 'إيرادات خدمات ما بعد البيع', 'income_operating'),
|
||||
('6030', 'Car Rental Income', 'إيرادات تأجير سيارات', 'income_operating'),
|
||||
('6040', 'Other Income', 'إيرادات أخرى', 'income_other'),
|
||||
|
||||
# Expenses
|
||||
('7010', 'Cost of Goods Sold', 'تكلفة البضاعة المباعة', 'expense_cogs'),
|
||||
('7015', 'Spare Parts Cost Consumed', 'تكلفة قطع الغيار المستهلكة', 'expense_cogs'),
|
||||
('7020', 'Salaries & Wages', 'رواتب وأجور', 'expense_operating'),
|
||||
('7030', 'Rent', 'إيجار', 'expense_operating'),
|
||||
('7040', 'Utilities', 'كهرباء ومياه', 'expense_operating'),
|
||||
('7050', 'Advertising & Marketing', 'دعاية وإعلان', 'expense_operating'),
|
||||
('7060', 'Maintenance', 'صيانة', 'expense_operating'),
|
||||
('7070', 'Operating Expenses', 'مصاريف تشغيلية', 'expense_operating'),
|
||||
('7080', 'Depreciation', 'استهلاك أصول ثابتة', 'expense_depreciation'),
|
||||
('7090', 'Fees & Taxes', 'رسوم وضرائب', 'expense_operating'),
|
||||
('7100', 'Bank Charges', 'مصاريف بنكية', 'expense_operating'),
|
||||
('7110', 'Other Expenses', 'مصاريف أخرى', 'expense_other'),
|
||||
]
|
||||
|
||||
# Create accounts
|
||||
created_count = 0
|
||||
for code, name_en, name_ar, role in ACCOUNTS:
|
||||
acc, created = AccountModel.objects.get_or_create(
|
||||
coa=coa,
|
||||
code=code,
|
||||
defaults={
|
||||
'name': name_en,
|
||||
'name_ar': name_ar,
|
||||
'role_default': role,
|
||||
'active': True,
|
||||
'balance_type': 'debit' if role.startswith(('asset', 'expense')) else 'credit'
|
||||
}
|
||||
)
|
||||
if created:
|
||||
created_count += 1
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f'Successfully created {created_count} accounts'))
|
||||
self.stdout.write(self.style.SUCCESS(f'Total accounts in COA: {len(ACCOUNTS)}'))
|
||||
127
inventory/management/commands/gemini.py
Normal file
127
inventory/management/commands/gemini.py
Normal file
@ -0,0 +1,127 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django_ledger.models import AccountModel, EntityModel, AccountRole, AccountType # تم التعديل هنا
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'ينشئ أو يحدث حسابات Django Ledger المحددة لكيان معين.'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# إضافة وسيط لتحديد اسم الكيان
|
||||
parser.add_argument(
|
||||
'--entity_name',
|
||||
type=str,
|
||||
default='qemini', # اسم الكيان الافتراضي
|
||||
help='اسم الكيان الذي سيتم ربط الحسابات به (افتراضي: qemini).'
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
entity_name = options['entity_name']
|
||||
|
||||
# البحث عن الكيان بناءً على الاسم المقدم
|
||||
try:
|
||||
entity = EntityModel.objects.get(name__iexact=entity_name)
|
||||
self.stdout.write(self.style.SUCCESS(f"تم العثور على الكيان: {entity.name}"))
|
||||
except EntityModel.DoesNotExist:
|
||||
raise CommandError(f"لم يتم العثور على كيان باسم '{entity_name}'. يرجى التأكد من وجوده.")
|
||||
except Exception as e:
|
||||
raise CommandError(f"حدث خطأ أثناء جلب الكيان '{entity_name}': {e}")
|
||||
|
||||
# قائمة الحسابات المراد إنشاؤها
|
||||
accounts_data = [
|
||||
# الأصول (مدين)
|
||||
{'code': '1010', 'name': 'Cash on Hand', 'role': AccountRole.CASH, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1020', 'name': 'Bank', 'role': AccountRole.CASH, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1030', 'name': 'Accounts Receivable', 'role': AccountRole.RECEIVABLE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1040', 'name': 'Inventory (Cars)', 'role': AccountRole.INVENTORY, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1045', 'name': 'Spare Parts Inventory', 'role': AccountRole.INVENTORY, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1050', 'name': 'Employee Advances', 'role': AccountRole.OTHER_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1060', 'name': 'Prepaid Expenses', 'role': AccountRole.OTHER_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '1070', 'name': 'Notes Receivable', 'role': AccountRole.RECEIVABLE, 'balance_type': AccountType.DEBIT},
|
||||
|
||||
{'code': '2010', 'name': 'Lands', 'role': AccountRole.FIXED_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2011', 'name': 'Buildings', 'role': AccountRole.FIXED_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2012', 'name': 'Company Vehicles', 'role': AccountRole.FIXED_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2013', 'name': 'Equipment & Tools', 'role': AccountRole.FIXED_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2014', 'name': 'Furniture & Fixtures', 'role': AccountRole.FIXED_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2015', 'name': 'Other Fixed Assets', 'role': AccountRole.FIXED_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2020', 'name': 'Long-term Investments', 'role': AccountRole.OTHER_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '2030', 'name': 'Intangible Assets', 'role': AccountRole.INTANGIBLE_ASSET, 'balance_type': AccountType.DEBIT},
|
||||
|
||||
# الخصوم (دائن)
|
||||
{'code': '3010', 'name': 'Accounts Payable', 'role': AccountRole.PAYABLE, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '3020', 'name': 'Notes Payable', 'role': AccountRole.PAYABLE, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '3030', 'name': 'Short-term Loans', 'role': AccountRole.OTHER_LIABILITY, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '3040', 'name': 'Employee Payables', 'role': AccountRole.OTHER_LIABILITY, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '3050', 'name': 'Accrued Expenses', 'role': AccountRole.OTHER_LIABILITY, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '3060', 'name': 'Accrued Taxes', 'role': AccountRole.OTHER_LIABILITY, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '3070', 'name': 'Provisions', 'role': AccountRole.PROVISION, 'balance_type': AccountType.CREDIT},
|
||||
|
||||
{'code': '4010', 'name': 'Long-term Bank Loans', 'role': AccountRole.LONG_TERM_DEBT, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '4020', 'name': 'Lease Liabilities', 'role': AccountRole.LONG_TERM_DEBT, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '4030', 'name': 'Other Long-term Liabilities', 'role': AccountRole.LONG_TERM_DEBT, 'balance_type': AccountType.CREDIT},
|
||||
|
||||
# حقوق الملكية (دائن)
|
||||
{'code': '5010', 'name': 'Capital', 'role': AccountRole.EQUITY, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '5020', 'name': 'Statutory Reserve', 'role': AccountRole.RETAINED_EARNINGS, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '5030', 'name': 'Retained Earnings', 'role': AccountRole.RETAINED_EARNINGS, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '5040', 'name': 'Profit & Loss for the Period', 'role': AccountRole.RETAINED_EARNINGS, 'balance_type': AccountType.CREDIT},
|
||||
|
||||
# الإيرادات (دائن)
|
||||
{'code': '6010', 'name': 'Car Sales', 'role': AccountRole.SALES, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '6020', 'name': 'After-Sales Services', 'role': AccountRole.SALES, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '6030', 'name': 'Car Rental Income', 'role': AccountRole.SALES, 'balance_type': AccountType.CREDIT},
|
||||
{'code': '6040', 'name': 'Other Income', 'role': AccountRole.OTHER_INCOME, 'balance_type': AccountType.CREDIT},
|
||||
|
||||
# المصروفات (مدين)
|
||||
{'code': '7010', 'name': 'Cost of Goods Sold', 'role': AccountRole.COST_OF_GOODS_SOLD, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7015', 'name': 'Spare Parts Cost Consumed', 'role': AccountRole.COST_OF_GOODS_SOLD, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7020', 'name': 'Salaries & Wages', 'role': AccountRole.OPERATING_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7030', 'name': 'Rent', 'role': AccountRole.OPERATING_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7040', 'name': 'Utilities', 'role': AccountRole.OPERATING_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7050', 'name': 'Advertising & Marketing', 'role': AccountRole.OPERATING_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7060', 'name': 'Maintenance', 'role': AccountRole.OPERATING_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7070', 'name': 'Operating Expenses', 'role': AccountRole.OPERATING_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7080', 'name': 'Depreciation', 'role': AccountRole.DEPRECIATION_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7090', 'name': 'Fees & Taxes', 'role': AccountRole.OTHER_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7100', 'name': 'Bank Charges', 'role': AccountRole.OTHER_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
{'code': '7110', 'name': 'Other Expenses', 'role': AccountRole.OTHER_EXPENSE, 'balance_type': AccountType.DEBIT},
|
||||
]
|
||||
|
||||
created_count = 0
|
||||
updated_count = 0
|
||||
|
||||
for acc_data in accounts_data:
|
||||
try:
|
||||
# البحث عن الحساب الموجود أو إنشاء حساب جديد
|
||||
account, created = AccountModel.objects.get_or_create(
|
||||
entity=entity,
|
||||
code=acc_data['code'],
|
||||
defaults={
|
||||
'name': acc_data['name'],
|
||||
'role': acc_data['role'], # تم التعديل هنا
|
||||
'balance_type': acc_data['balance_type'] # تم التعديل هنا
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
created_count += 1
|
||||
self.stdout.write(self.style.SUCCESS(f"تم إنشاء الحساب: {account.code} - {account.name}"))
|
||||
else:
|
||||
# إذا كان الحساب موجودًا، نقوم بتحديث اسمه ودوره ونوع رصيده إذا كان مختلفًا
|
||||
if (account.name != acc_data['name'] or
|
||||
account.role != acc_data['role'] or # تم التعديل هنا
|
||||
account.balance_type != acc_data['balance_type']): # تم التعديل هنا
|
||||
account.name = acc_data['name']
|
||||
account.role = acc_data['role']
|
||||
account.balance_type = acc_data['balance_type']
|
||||
account.save()
|
||||
updated_count += 1
|
||||
self.stdout.write(self.style.WARNING(f"تم تحديث الحساب: {account.code} - {account.name}"))
|
||||
else:
|
||||
self.stdout.write(f"الحساب موجود بالفعل ولم يتطلب تحديث: {account.code} - {account.name}")
|
||||
|
||||
except Exception as e:
|
||||
self.stdout.write(self.style.ERROR(f"خطأ في معالجة الحساب {acc_data['code']} - {acc_data['name']}: {e}"))
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f"\nعملية إنشاء/تحديث الحسابات اكتملت."))
|
||||
self.stdout.write(self.style.SUCCESS(f"عدد الحسابات التي تم إنشاؤها حديثًا: {created_count}"))
|
||||
self.stdout.write(self.style.SUCCESS(f"عدد الحسابات التي تم تحديثها: {updated_count}"))
|
||||
123
inventory/management/commands/gpt.py
Normal file
123
inventory/management/commands/gpt.py
Normal file
@ -0,0 +1,123 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django_ledger.models.entity import EntityModel
|
||||
from django_ledger.models.chart_of_accounts import ChartOfAccountModel
|
||||
from django_ledger.models.accounts import AccountModel
|
||||
from django_ledger.models.roles import RoleModel
|
||||
from django_ledger.models.balance_types import BalanceTypeModel
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Create the chart of accounts for the ChatGPT entity'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# Step 1: Retrieve or create the entity
|
||||
entity, created = EntityModel.objects.get_or_create(name="chatgpt")
|
||||
if created:
|
||||
self.stdout.write(self.style.SUCCESS("Entity 'chatgpt' created."))
|
||||
else:
|
||||
self.stdout.write(self.style.WARNING("Entity 'chatgpt' already exists."))
|
||||
|
||||
# Step 2: Retrieve or create the default Chart of Accounts
|
||||
if hasattr(entity, 'default_coa') and entity.default_coa:
|
||||
coa = entity.default_coa
|
||||
self.stdout.write(self.style.WARNING("Default Chart of Accounts already exists."))
|
||||
else:
|
||||
coa = ChartOfAccountModel.objects.create(name="Default CoA", entity=entity)
|
||||
entity.default_coa = coa
|
||||
entity.save()
|
||||
self.stdout.write(self.style.SUCCESS("Default Chart of Accounts created."))
|
||||
|
||||
# Step 3: Define the accounts to be created
|
||||
accounts = [
|
||||
(1010, 'Cash on Hand', 'الصندوق', 'asset'),
|
||||
(1020, 'Bank', 'البنك', 'asset'),
|
||||
(1030, 'Accounts Receivable', 'العملاء', 'asset'),
|
||||
(1040, 'Inventory (Cars)', 'مخزون السيارات', 'asset'),
|
||||
(1045, 'Spare Parts Inventory', 'مخزون قطع الغيار', 'asset'),
|
||||
(1050, 'Employee Advances', 'سُلف وأمانات الموظفين', 'asset'),
|
||||
(1060, 'Prepaid Expenses', 'مصروفات مدفوعة مقدماً', 'asset'),
|
||||
(1070, 'Notes Receivable', 'أوراق القبض', 'asset'),
|
||||
(2010, 'Lands', 'أراضي', 'asset'),
|
||||
(2011, 'Buildings', 'مباني', 'asset'),
|
||||
(2012, 'Company Vehicles', 'سيارات الشركة', 'asset'),
|
||||
(2013, 'Equipment & Tools', 'أجهزة ومعدات', 'asset'),
|
||||
(2014, 'Furniture & Fixtures', 'أثاث وديكور', 'asset'),
|
||||
(2015, 'Other Fixed Assets', 'أصول ثابتة أخرى', 'asset'),
|
||||
(2020, 'Long-term Investments', 'استثمارات طويلة الأجل', 'asset'),
|
||||
(2030, 'Intangible Assets', 'أصول غير ملموسة', 'asset'),
|
||||
(3010, 'Accounts Payable', 'الموردين', 'liability'),
|
||||
(3020, 'Notes Payable', 'أوراق الدفع', 'liability'),
|
||||
(3030, 'Short-term Loans', 'قروض قصيرة الأجل', 'liability'),
|
||||
(3040, 'Employee Payables', 'السلف المستحقة', 'liability'),
|
||||
(3050, 'Accrued Expenses', 'مصروفات مستحقة', 'liability'),
|
||||
(3060, 'Accrued Taxes', 'ضرائب مستحقة', 'liability'),
|
||||
(3070, 'Provisions', 'مخصصات', 'liability'),
|
||||
(4010, 'Long-term Bank Loans', 'قروض طويلة الأجل', 'liability'),
|
||||
(4020, 'Lease Liabilities', 'التزامات تمويلية', 'liability'),
|
||||
(4030, 'Other Long-term Liabilities', 'التزامات أخرى طويلة الأجل', 'liability'),
|
||||
(5010, 'Capital', 'رأس المال', 'equity'),
|
||||
(5020, 'Statutory Reserve', 'الاحتياطي القانوني', 'equity'),
|
||||
(5030, 'Retained Earnings', 'احتياطي الأرباح', 'equity'),
|
||||
(5040, 'Profit & Loss for the Period', 'أرباح وخسائر الفترة', 'equity'),
|
||||
(6010, 'Car Sales', 'مبيعات السيارات', 'income'),
|
||||
(6020, 'After-Sales Services', 'إيرادات خدمات ما بعد البيع', 'income'),
|
||||
(6030, 'Car Rental Income', 'إيرادات تأجير سيارات', 'income'),
|
||||
(6040, 'Other Income', 'إيرادات أخرى', 'income'),
|
||||
(7010, 'Cost of Goods Sold', 'تكلفة البضاعة المباعة', 'expense'),
|
||||
(7015, 'Spare Parts Cost Consumed', 'تكلفة قطع الغيار المستهلكة', 'expense'),
|
||||
(7020, 'Salaries & Wages', 'رواتب وأجور', 'expense'),
|
||||
(7030, 'Rent', 'إيجار', 'expense'),
|
||||
(7040, 'Utilities', 'كهرباء ومياه', 'expense'),
|
||||
(7050, 'Advertising & Marketing', 'دعاية وإعلان', 'expense'),
|
||||
(7060, 'Maintenance', 'صيانة', 'expense'),
|
||||
(7070, 'Operating Expenses', 'مصاريف تشغيلية', 'expense'),
|
||||
(7080, 'Depreciation', 'استهلاك أصول ثابتة', 'expense'),
|
||||
(7090, 'Fees & Taxes', 'رسوم وضرائب', 'expense'),
|
||||
(7100, 'Bank Charges', 'مصاريف بنكية', 'expense'),
|
||||
(7110, 'Other Expenses', 'مصاريف أخرى', 'expense'),
|
||||
]
|
||||
|
||||
# Mapping for role and balance_type
|
||||
role_mapping = {
|
||||
'asset': 'ASSET',
|
||||
'liability': 'LIABILITY',
|
||||
'equity': 'EQUITY',
|
||||
'income': 'INCOME',
|
||||
'expense': 'EXPENSE',
|
||||
}
|
||||
|
||||
balance_type_mapping = {
|
||||
'ASSET': 'DEBIT',
|
||||
'LIABILITY': 'CREDIT',
|
||||
'EQUITY': 'CREDIT',
|
||||
'INCOME': 'CREDIT',
|
||||
'EXPENSE': 'DEBIT',
|
||||
}
|
||||
|
||||
# Step 4: Delete existing accounts in the CoA
|
||||
existing_accounts = AccountModel.objects.filter(coa_model=coa)
|
||||
count_deleted = existing_accounts.count()
|
||||
existing_accounts.delete()
|
||||
self.stdout.write(self.style.SUCCESS(f"Deleted {count_deleted} existing accounts."))
|
||||
|
||||
# Step 5: Create new accounts
|
||||
for code, name_en, name_ar, role_slug in accounts:
|
||||
role = RoleModel.objects.get(slug=role_slug)
|
||||
balance_type = BalanceTypeModel.objects.get(role=role)
|
||||
parent = None # Set to None for root accounts
|
||||
|
||||
# Determine parent-child relationships
|
||||
if code in [1040, 1045, 2012, 2013, 2014, 2015, 2020, 2030]:
|
||||
parent_code = code - 10 # Example logic for determining parent code
|
||||
parent = AccountModel.objects.get(coa_model=coa, code=parent_code)
|
||||
|
||||
account = AccountModel.objects.create(
|
||||
coa_model=coa,
|
||||
code=code,
|
||||
name=name_en,
|
||||
arabic_name=name_ar,
|
||||
role=role,
|
||||
balance_type=balance_type,
|
||||
parent=parent,
|
||||
depth=parent.depth + 1 if parent else 0,
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(f"Account {name_en} ({code}) created."))
|
||||
76
inventory/management/commands/qwen.py
Normal file
76
inventory/management/commands/qwen.py
Normal file
@ -0,0 +1,76 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django_ledger.models import AccountModel
|
||||
from django_ledger.constants import ACCOUNT_TYPE_ASSET, ACCOUNT_TYPE_LIABILITY, ACCOUNT_TYPE_EQUITY, ACCOUNT_TYPE_INCOME, ACCOUNT_TYPE_EXPENSE
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Creates default accounts for the entity "qwen" in Django Ledger'
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
self.stdout.write('Creating accounts for entity "qwen"...')
|
||||
|
||||
accounts_data = [
|
||||
# Assets (Debit Balance)
|
||||
{'code': '1010', 'name_ar': 'الصندوق', 'name_en': 'Cash on Hand', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1020', 'name_ar': 'البنك', 'name_en': 'Bank', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1030', 'name_ar': 'العملاء', 'name_en': 'Accounts Receivable', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1040', 'name_ar': 'مخزون السيارات', 'name_en': 'Inventory (Cars)', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1045', 'name_ar': 'مخزون قطع الغيار', 'name_en': 'Spare Parts Inventory', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1050', 'name_ar': 'سُلف وأمانات الموظفين', 'name_en': 'Employee Advances', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1060', 'name_ar': 'مصروفات مدفوعة مقدماً', 'name_en': 'Prepaid Expenses', 'type': ACCOUNT_TYPE_ASSET},
|
||||
{'code': '1070', 'name_ar': 'أوراق القبض', 'name_en': 'Notes Receivable', 'type': ACCOUNT_TYPE_ASSET},
|
||||
|
||||
# Liabilities (Credit Balance)
|
||||
{'code': '3010', 'name_ar': 'الموردين', 'name_en': 'Accounts Payable', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
{'code': '3020', 'name_ar': 'أوراق الدفع', 'name_en': 'Notes Payable', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
{'code': '3030', 'name_ar': 'قروض قصيرة الأجل', 'name_en': 'Short-term Loans', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
{'code': '3040', 'name_ar': 'السلف المستحقة', 'name_en': 'Employee Payables', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
{'code': '3050', 'name_ar': 'مصروفات مستحقة', 'name_en': 'Accrued Expenses', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
{'code': '3060', 'name_ar': 'ضرائب مستحقة', 'name_en': 'Accrued Taxes', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
{'code': '3070', 'name_ar': 'مخصصات', 'name_en': 'Provisions', 'type': ACCOUNT_TYPE_LIABILITY},
|
||||
|
||||
# Equity (Credit Balance)
|
||||
{'code': '5010', 'name_ar': 'رأس المال', 'name_en': 'Capital', 'type': ACCOUNT_TYPE_EQUITY},
|
||||
{'code': '5020', 'name_ar': 'الاحتياطي القانوني', 'name_en': 'Statutory Reserve', 'type': ACCOUNT_TYPE_EQUITY},
|
||||
{'code': '5030', 'name_ar': 'احتياطي الأرباح', 'name_en': 'Retained Earnings', 'type': ACCOUNT_TYPE_EQUITY},
|
||||
{'code': '5040', 'name_ar': 'أرباح وخسائر الفترة', 'name_en': 'Profit & Loss for the Period', 'type': ACCOUNT_TYPE_EQUITY},
|
||||
|
||||
# Income (Revenue) (Credit Balance)
|
||||
{'code': '6010', 'name_ar': 'مبيعات السيارات', 'name_en': 'Car Sales', 'type': ACCOUNT_TYPE_INCOME},
|
||||
{'code': '6020', 'name_ar': 'إيرادات خدمات ما بعد البيع', 'name_en': 'After-Sales Services', 'type': ACCOUNT_TYPE_INCOME},
|
||||
{'code': '6030', 'name_ar': 'إيرادات تأجير سيارات', 'name_en': 'Car Rental Income', 'type': ACCOUNT_TYPE_INCOME},
|
||||
{'code': '6040', 'name_ar': 'إيرادات أخرى', 'name_en': 'Other Income', 'type': ACCOUNT_TYPE_INCOME},
|
||||
|
||||
# Expenses (Debit Balance)
|
||||
{'code': '7010', 'name_ar': 'تكلفة البضاعة المباعة', 'name_en': 'Cost of Goods Sold', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7015', 'name_ar': 'تكلفة قطع الغيار المستهلكة', 'name_en': 'Spare Parts Cost Consumed', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7020', 'name_ar': 'رواتب وأجور', 'name_en': 'Salaries & Wages', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7030', 'name_ar': 'إيجار', 'name_en': 'Rent', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7040', 'name_ar': 'كهرباء ومياه', 'name_en': 'Utilities', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7050', 'name_ar': 'دعاية وإعلان', 'name_en': 'Advertising & Marketing', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7060', 'name_ar': 'صيانة', 'name_en': 'Maintenance', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7070', 'name_ar': 'مصاريف تشغيلية', 'name_en': 'Operating Expenses', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7080', 'name_ar': 'استهلاك أصول ثابتة', 'name_en': 'Depreciation', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7090', 'name_ar': 'رسوم وضرائب', 'name_en': 'Fees & Taxes', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7100', 'name_ar': 'مصاريف بنكية', 'name_en': 'Bank Charges', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
{'code': '7110', 'name_ar': 'مصاريف أخرى', 'name_en': 'Other Expenses', 'type': ACCOUNT_TYPE_EXPENSE},
|
||||
]
|
||||
|
||||
created_count = 0
|
||||
for acc in accounts_data:
|
||||
account, created = objects.get_or_create(
|
||||
code=acc['code'],
|
||||
defaults={
|
||||
'name': acc['name_ar'],
|
||||
'name_en': acc['name_en'],
|
||||
'account_type': acc['type'],
|
||||
'balance_type': BALANCE_TYPE_CREDIT if acc['type'] in [
|
||||
ACCOUNT_TYPE_LIABILITY,
|
||||
ACCOUNT_TYPE_EQUITY,
|
||||
ACCOUNT_TYPE_INCOME
|
||||
] else BALANCE_TYPE_DEBIT
|
||||
}
|
||||
)
|
||||
if created:
|
||||
created_count += 1
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f'Successfully created {created_count} accounts for "qwen".'))
|
||||
@ -1965,6 +1965,10 @@ class Opportunity(models.Model):
|
||||
def get_tasks(self):
|
||||
return self._get_filter(Tasks)
|
||||
|
||||
def get_meetings(self):
|
||||
return self.lead.get_meetings()
|
||||
def get_calls(self):
|
||||
return self.lead.get_calls()
|
||||
def get_schedules(self):
|
||||
return self.lead.get_all_schedules().filter(
|
||||
scheduled_at__gt=timezone.now()
|
||||
|
||||
@ -25,6 +25,750 @@ def create_settings(pk):
|
||||
|
||||
@background
|
||||
def create_coa_accounts(pk):
|
||||
with transaction.atomic():
|
||||
instance = Dealer.objects.select_for_update().get(pk=pk)
|
||||
entity = instance.entity
|
||||
coa = entity.get_default_coa()
|
||||
|
||||
# accounts_data = [
|
||||
# # Current Assets (must start with 1)
|
||||
# {
|
||||
# 'code': '1010',
|
||||
# 'name': 'Cash on Hand',
|
||||
# 'role': roles.ASSET_CA_CASH,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': True,
|
||||
# },
|
||||
# {
|
||||
# 'code': '1020',
|
||||
# 'name': 'Bank',
|
||||
# 'role': roles.ASSET_CA_CASH,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': True,
|
||||
# },
|
||||
# {
|
||||
# 'code': '1030',
|
||||
# 'name': 'Accounts Receivable',
|
||||
# 'role': roles.ASSET_CA_RECEIVABLES,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': True
|
||||
# },
|
||||
# {
|
||||
# 'code': '1040',
|
||||
# 'name': 'Inventory (Cars)',
|
||||
# 'role': roles.ASSET_CA_INVENTORY,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': True
|
||||
# },
|
||||
# {
|
||||
# 'code': '1045',
|
||||
# 'name': 'Spare Parts Inventory',
|
||||
# 'role': roles.ASSET_CA_INVENTORY,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1050',
|
||||
# 'name': 'Employee Advances',
|
||||
# 'role': roles.ASSET_CA_RECEIVABLES,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1060',
|
||||
# 'name': 'Prepaid Expenses',
|
||||
# 'role': roles.ASSET_CA_PREPAID,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1070',
|
||||
# 'name': 'Notes Receivable',
|
||||
# 'role': roles.ASSET_LTI_NOTES_RECEIVABLE,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
|
||||
# # Fixed Assets (must also start with 1)
|
||||
# {
|
||||
# 'code': '1110',
|
||||
# 'name': 'Lands',
|
||||
# 'role': roles.ASSET_LTI_LAND,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1111',
|
||||
# 'name': 'Buildings',
|
||||
# 'role': roles.ASSET_PPE_BUILDINGS,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1112',
|
||||
# 'name': 'Company Vehicles',
|
||||
# 'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1113',
|
||||
# 'name': 'Equipment & Tools',
|
||||
# 'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1114',
|
||||
# 'name': 'Furniture & Fixtures',
|
||||
# 'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1115',
|
||||
# 'name': 'Other Fixed Assets',
|
||||
# 'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1120',
|
||||
# 'name': 'Long-term Investments',
|
||||
# 'role': roles.ASSET_LTI_SECURITIES,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '1130',
|
||||
# 'name': 'Intangible Assets',
|
||||
# 'role': roles.ASSET_INTANGIBLE_ASSETS,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
|
||||
# # Current Liabilities (must start with 2)
|
||||
# {
|
||||
# 'code': '2010',
|
||||
# 'name': 'Accounts Payable',
|
||||
# 'role': roles.LIABILITY_CL_ACC_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': True
|
||||
# },
|
||||
# {
|
||||
# 'code': '2020',
|
||||
# 'name': 'Notes Payable',
|
||||
# 'role': roles.LIABILITY_CL_ST_NOTES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2030',
|
||||
# 'name': 'Short-term Loans',
|
||||
# 'role': roles.LIABILITY_CL_ST_NOTES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2040',
|
||||
# 'name': 'Employee Payables',
|
||||
# 'role': roles.LIABILITY_CL_WAGES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2050',
|
||||
# 'name': 'Accrued Expenses',
|
||||
# 'role': roles.LIABILITY_CL_OTHER,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2060',
|
||||
# 'name': 'Accrued Taxes',
|
||||
# 'role': roles.LIABILITY_CL_TAXES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2070',
|
||||
# 'name': 'Provisions',
|
||||
# 'role': roles.LIABILITY_CL_OTHER,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
|
||||
# # Long-term Liabilities (must also start with 2)
|
||||
# {
|
||||
# 'code': '2210',
|
||||
# 'name': 'Long-term Bank Loans',
|
||||
# 'role': roles.LIABILITY_LTL_NOTES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2220',
|
||||
# 'name': 'Lease Liabilities',
|
||||
# 'role': roles.LIABILITY_LTL_NOTES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '2230',
|
||||
# 'name': 'Other Long-term Liabilities',
|
||||
# 'role': roles.LIABILITY_LTL_NOTES_PAYABLE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
|
||||
# # Equity (must start with 3)
|
||||
# {
|
||||
# 'code': '3010',
|
||||
# 'name': 'Capital',
|
||||
# 'role': roles.EQUITY_CAPITAL,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': True
|
||||
# },
|
||||
# {
|
||||
# 'code': '3020',
|
||||
# 'name': 'Statutory Reserve',
|
||||
# 'role': roles.EQUITY_ADJUSTMENT,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '3030',
|
||||
# 'name': 'Retained Earnings',
|
||||
# 'role': roles.EQUITY_ADJUSTMENT,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '3040',
|
||||
# 'name': 'Profit & Loss for the Period',
|
||||
# 'role': roles.EQUITY_ADJUSTMENT,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
|
||||
# # Revenue (must start with 4)
|
||||
# {
|
||||
# 'code': '4010',
|
||||
# 'name': 'Car Sales',
|
||||
# 'role': roles.INCOME_OPERATIONAL,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': True
|
||||
# },
|
||||
# {
|
||||
# 'code': '4020',
|
||||
# 'name': 'After-Sales Services',
|
||||
# 'role': roles.INCOME_OPERATIONAL,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '4030',
|
||||
# 'name': 'Car Rental Income',
|
||||
# 'role': roles.INCOME_PASSIVE,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '4040',
|
||||
# 'name': 'Other Income',
|
||||
# 'role': roles.INCOME_OTHER,
|
||||
# 'balance_type': roles.CREDIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
|
||||
# # Expenses (must start with 5 for COGS, 6 for others)
|
||||
# {
|
||||
# 'code': '5010',
|
||||
# 'name': 'Cost of Goods Sold',
|
||||
# 'role': roles.COGS,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': True
|
||||
# },
|
||||
# {
|
||||
# 'code': '5015',
|
||||
# 'name': 'Spare Parts Cost Consumed',
|
||||
# 'role': roles.COGS,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6010',
|
||||
# 'name': 'Salaries & Wages',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6020',
|
||||
# 'name': 'Rent',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6030',
|
||||
# 'name': 'Utilities',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6040',
|
||||
# 'name': 'Advertising & Marketing',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6050',
|
||||
# 'name': 'Maintenance',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6060',
|
||||
# 'name': 'Operating Expenses',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6070',
|
||||
# 'name': 'Depreciation',
|
||||
# 'role': roles.EXPENSE_DEPRECIATION,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6080',
|
||||
# 'name': 'Fees & Taxes',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6090',
|
||||
# 'name': 'Bank Charges',
|
||||
# 'role': roles.EXPENSE_OPERATIONAL,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# },
|
||||
# {
|
||||
# 'code': '6100',
|
||||
# 'name': 'Other Expenses',
|
||||
# 'role': roles.EXPENSE_OTHER,
|
||||
# 'balance_type': roles.DEBIT,
|
||||
# 'locked': False
|
||||
# }
|
||||
# ]
|
||||
|
||||
accounts_data = [
|
||||
# Current Assets (must start with 1)
|
||||
{
|
||||
'code': '1010',
|
||||
'name': 'Cash on Hand',
|
||||
'role': roles.ASSET_CA_CASH,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': True,
|
||||
'default': True # Default for ASSET_CA_CASH
|
||||
},
|
||||
{
|
||||
'code': '1020',
|
||||
'name': 'Bank',
|
||||
'role': roles.ASSET_CA_CASH,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': True,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '1030',
|
||||
'name': 'Accounts Receivable',
|
||||
'role': roles.ASSET_CA_RECEIVABLES,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': True,
|
||||
'default': True # Default for ASSET_CA_RECEIVABLES
|
||||
},
|
||||
{
|
||||
'code': '1040',
|
||||
'name': 'Inventory (Cars)',
|
||||
'role': roles.ASSET_CA_INVENTORY,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': True,
|
||||
'default': True # Default for ASSET_CA_INVENTORY
|
||||
},
|
||||
{
|
||||
'code': '1045',
|
||||
'name': 'Spare Parts Inventory',
|
||||
'role': roles.ASSET_CA_INVENTORY,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '1050',
|
||||
'name': 'Employee Advances',
|
||||
'role': roles.ASSET_CA_RECEIVABLES,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '1060',
|
||||
'name': 'Prepaid Expenses',
|
||||
'role': roles.ASSET_CA_PREPAID,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_CA_PREPAID
|
||||
},
|
||||
{
|
||||
'code': '1070',
|
||||
'name': 'Notes Receivable',
|
||||
'role': roles.ASSET_LTI_NOTES_RECEIVABLE,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_LTI_NOTES_RECEIVABLE
|
||||
},
|
||||
|
||||
# Fixed Assets (must also start with 1)
|
||||
{
|
||||
'code': '1110',
|
||||
'name': 'Lands',
|
||||
'role': roles.ASSET_LTI_LAND,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_LTI_LAND
|
||||
},
|
||||
{
|
||||
'code': '1111',
|
||||
'name': 'Buildings',
|
||||
'role': roles.ASSET_PPE_BUILDINGS,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_PPE_BUILDINGS
|
||||
},
|
||||
{
|
||||
'code': '1112',
|
||||
'name': 'Company Vehicles',
|
||||
'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_PPE_EQUIPMENT
|
||||
},
|
||||
{
|
||||
'code': '1113',
|
||||
'name': 'Equipment & Tools',
|
||||
'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '1114',
|
||||
'name': 'Furniture & Fixtures',
|
||||
'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '1115',
|
||||
'name': 'Other Fixed Assets',
|
||||
'role': roles.ASSET_PPE_EQUIPMENT,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '1120',
|
||||
'name': 'Long-term Investments',
|
||||
'role': roles.ASSET_LTI_SECURITIES,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_LTI_SECURITIES
|
||||
},
|
||||
{
|
||||
'code': '1130',
|
||||
'name': 'Intangible Assets',
|
||||
'role': roles.ASSET_INTANGIBLE_ASSETS,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for ASSET_INTANGIBLE_ASSETS
|
||||
},
|
||||
|
||||
# Current Liabilities (must start with 2)
|
||||
{
|
||||
'code': '2010',
|
||||
'name': 'Accounts Payable',
|
||||
'role': roles.LIABILITY_CL_ACC_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': True,
|
||||
'default': True # Default for LIABILITY_CL_ACC_PAYABLE
|
||||
},
|
||||
{
|
||||
'code': '2020',
|
||||
'name': 'Notes Payable',
|
||||
'role': roles.LIABILITY_CL_ST_NOTES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for LIABILITY_CL_ST_NOTES_PAYABLE
|
||||
},
|
||||
{
|
||||
'code': '2030',
|
||||
'name': 'Short-term Loans',
|
||||
'role': roles.LIABILITY_CL_ST_NOTES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '2040',
|
||||
'name': 'Employee Payables',
|
||||
'role': roles.LIABILITY_CL_WAGES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for LIABILITY_CL_WAGES_PAYABLE
|
||||
},
|
||||
{
|
||||
'code': '2050',
|
||||
'name': 'Accrued Expenses',
|
||||
'role': roles.LIABILITY_CL_OTHER,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for LIABILITY_CL_OTHER
|
||||
},
|
||||
{
|
||||
'code': '2060',
|
||||
'name': 'Accrued Taxes',
|
||||
'role': roles.LIABILITY_CL_TAXES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for LIABILITY_CL_TAXES_PAYABLE
|
||||
},
|
||||
{
|
||||
'code': '2070',
|
||||
'name': 'Provisions',
|
||||
'role': roles.LIABILITY_CL_OTHER,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
|
||||
# Long-term Liabilities (must also start with 2)
|
||||
{
|
||||
'code': '2210',
|
||||
'name': 'Long-term Bank Loans',
|
||||
'role': roles.LIABILITY_LTL_NOTES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for LIABILITY_LTL_NOTES_PAYABLE
|
||||
},
|
||||
{
|
||||
'code': '2220',
|
||||
'name': 'Lease Liabilities',
|
||||
'role': roles.LIABILITY_LTL_NOTES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '2230',
|
||||
'name': 'Other Long-term Liabilities',
|
||||
'role': roles.LIABILITY_LTL_NOTES_PAYABLE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
|
||||
# Equity (must start with 3)
|
||||
{
|
||||
'code': '3010',
|
||||
'name': 'Capital',
|
||||
'role': roles.EQUITY_CAPITAL,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': True,
|
||||
'default': True # Default for EQUITY_CAPITAL
|
||||
},
|
||||
{
|
||||
'code': '3020',
|
||||
'name': 'Statutory Reserve',
|
||||
'role': roles.EQUITY_ADJUSTMENT,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for EQUITY_ADJUSTMENT
|
||||
},
|
||||
{
|
||||
'code': '3030',
|
||||
'name': 'Retained Earnings',
|
||||
'role': roles.EQUITY_ADJUSTMENT,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '3040',
|
||||
'name': 'Profit & Loss for the Period',
|
||||
'role': roles.EQUITY_ADJUSTMENT,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
|
||||
# Revenue (must start with 4)
|
||||
{
|
||||
'code': '4010',
|
||||
'name': 'Car Sales',
|
||||
'role': roles.INCOME_OPERATIONAL,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': True,
|
||||
'default': True # Default for INCOME_OPERATIONAL
|
||||
},
|
||||
{
|
||||
'code': '4020',
|
||||
'name': 'After-Sales Services',
|
||||
'role': roles.INCOME_OPERATIONAL,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '4030',
|
||||
'name': 'Car Rental Income',
|
||||
'role': roles.INCOME_PASSIVE,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for INCOME_PASSIVE
|
||||
},
|
||||
{
|
||||
'code': '4040',
|
||||
'name': 'Other Income',
|
||||
'role': roles.INCOME_OTHER,
|
||||
'balance_type': roles.CREDIT,
|
||||
'locked': False,
|
||||
'default': True # Default for INCOME_OTHER
|
||||
},
|
||||
|
||||
# Expenses (must start with 5 for COGS, 6 for others)
|
||||
{
|
||||
'code': '5010',
|
||||
'name': 'Cost of Goods Sold',
|
||||
'role': roles.COGS,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': True,
|
||||
'default': True # Default for COGS
|
||||
},
|
||||
{
|
||||
'code': '5015',
|
||||
'name': 'Spare Parts Cost Consumed',
|
||||
'role': roles.COGS,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6010',
|
||||
'name': 'Salaries & Wages',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for EXPENSE_OPERATIONAL
|
||||
},
|
||||
{
|
||||
'code': '6020',
|
||||
'name': 'Rent',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6030',
|
||||
'name': 'Utilities',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6040',
|
||||
'name': 'Advertising & Marketing',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6050',
|
||||
'name': 'Maintenance',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6060',
|
||||
'name': 'Operating Expenses',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6070',
|
||||
'name': 'Depreciation',
|
||||
'role': roles.EXPENSE_DEPRECIATION,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for EXPENSE_DEPRECIATION
|
||||
},
|
||||
{
|
||||
'code': '6080',
|
||||
'name': 'Fees & Taxes',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6090',
|
||||
'name': 'Bank Charges',
|
||||
'role': roles.EXPENSE_OPERATIONAL,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': False
|
||||
},
|
||||
{
|
||||
'code': '6100',
|
||||
'name': 'Other Expenses',
|
||||
'role': roles.EXPENSE_OTHER,
|
||||
'balance_type': roles.DEBIT,
|
||||
'locked': False,
|
||||
'default': True # Default for EXPENSE_OTHER
|
||||
}
|
||||
]
|
||||
|
||||
for account_data in accounts_data:
|
||||
try:
|
||||
account = entity.create_account(
|
||||
coa_model=coa,
|
||||
code=account_data['code'],
|
||||
name=_(account_data['name']),
|
||||
role=_(account_data['role']),
|
||||
balance_type=_(account_data['balance_type']),
|
||||
active=True
|
||||
)
|
||||
account.role_default = account_data['default']
|
||||
account.save()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
@background
|
||||
def create_coa_accounts1(pk):
|
||||
with transaction.atomic():
|
||||
instance = Dealer.objects.select_for_update().get(pk=pk)
|
||||
entity = instance.entity
|
||||
|
||||
@ -129,7 +129,7 @@ def period_navigation(context, base_url: str):
|
||||
def balance_sheet_statement(context, io_model, to_date=None):
|
||||
user_model = context['user']
|
||||
activity = context['request'].GET.get('activity')
|
||||
entity_slug = context['view'].kwargs.get('entity_slug')
|
||||
entity_slug = context['view'].kwargs.get('entity_slug')
|
||||
if not to_date:
|
||||
to_date = context['to_date']
|
||||
|
||||
@ -358,4 +358,9 @@ def splitlines(value):
|
||||
def currency_format(value):
|
||||
if not value:
|
||||
value = 0.00
|
||||
return number_format(value, decimal_pos=2, use_l10n=True, force_grouping=True)
|
||||
return number_format(value, decimal_pos=2, use_l10n=True, force_grouping=True)
|
||||
|
||||
|
||||
@register.filter
|
||||
def filter_by_role(accounts, role_prefix):
|
||||
return [account for account in accounts if account.role.startswith(role_prefix)]
|
||||
@ -4823,6 +4823,7 @@ class LeadDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
||||
lead=self.object
|
||||
)
|
||||
context["transfer_form"] = forms.LeadTransferForm()
|
||||
context["transfer_form"].fields["transfer_to"].queryset = (models.Staff.objects.filter(dealer=self.object.dealer,staff_type="sales"))
|
||||
context["activity_form"] = forms.ActivityForm()
|
||||
context["staff_task_form"] = forms.StaffTaskForm()
|
||||
context["note_form"] = forms.NoteForm()
|
||||
|
||||
@ -102,6 +102,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center g-3 text-center text-xxl-start">
|
||||
<div class="col-6 col-sm-auto d-flex flex-column align-items-center text-center">
|
||||
<h5 class="fw-bolder mb-2 text-body-highlight">{{ _("Related Records") }}</h5>
|
||||
<h6 class="fw-bolder mb-2 text-body-highlight">{{ _("Opportunity") }}</h6>
|
||||
{% if lead.opportunity %}
|
||||
<a href="{% url 'opportunity_detail' lead.opportunity.slug %}" class="">{{ lead.opportunity }}</a>
|
||||
{% else %}
|
||||
<p>{{ _("No Opportunity") }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
@ -469,25 +484,7 @@
|
||||
</thead>
|
||||
<tbody class="list" id="all-tasks-table-body">
|
||||
{% for task in tasks %}
|
||||
<tr class="task-{{task.pk}} hover-actions-trigger btn-reveal-trigger position-static {% if task.completed %}completed-task{% endif %}">
|
||||
<td class="fs-9 align-middle px-0 py-3">
|
||||
<div class="form-check mb-0 fs-8">
|
||||
<input class="form-check-input" type="checkbox" hx-post="{% url 'update_task' 'lead' task.pk %}" hx-trigger="change" hx-swap="outerHTML" hx-target=".task-{{task.pk}}" hx-select=".task-{{task.pk}}" />
|
||||
</div>
|
||||
</td>
|
||||
<td class="subject order align-middle white-space-nowrap py-2 ps-0"><a class="fw-semibold text-primary" href="">{{task.title}}</a>
|
||||
<div class="fs-10 d-block">{{task.description}}</div>
|
||||
</td>
|
||||
<td class="sent align-middle white-space-nowrap text-start fw-bold text-body-tertiary py-2">{{task.assigned_to}}</td>
|
||||
<td class="date align-middle white-space-nowrap text-body py-2">{{task.created|naturalday|capfirst}}</td>
|
||||
<td class="date align-middle white-space-nowrap text-body py-2">
|
||||
{% if task.completed %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-success"><i class="fa-solid fa-check"></i></span>
|
||||
{% else %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-warning"><i class="fa-solid fa-xmark"></i></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% include "partials/task.html" %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static humanize %}
|
||||
{% block title %}{{ _("Opportunity Detail") }}{% endblock title %}
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
.completed-task {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
{% block content %}
|
||||
<div class="row align-items-center justify-content-between g-3 mb-4">
|
||||
<div class="col-12 col-md-auto">
|
||||
@ -79,12 +87,12 @@
|
||||
<div class="col-12 overflow-auto" style="max-height: 200px;">
|
||||
<ul class="list-group list-group-flush">
|
||||
{% for event in opportunity.get_schedules %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<li class="list-group-item d-flex justify-content-between ">
|
||||
<span class="badge rounded-pill bg-phoenix-primary text-primary me-2 fs-9">{{ event.scheduled_type|capfirst }}</span>
|
||||
<span class="fs-9">{{ event.purpose }}</span>
|
||||
</div>
|
||||
<div class="fs-9">{{ event.scheduled_at|naturaltime|capfirst }}</div>
|
||||
<div class="fs-9 d-flex flex-column">
|
||||
<span class="fs-9">{{ event.purpose|capfirst }}</span>
|
||||
<span><span class="badge rounded-pill bg-phoenix-primary text-secondary"><span class="d-inline-block lh-sm me-1" data-feather="clock" style="height:16px;width:16px;"></span> {{ event.scheduled_at|naturaltime|capfirst }}</span></span>
|
||||
</div>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item text-center fs-9">{{ _("No upcoming events") }}</li>
|
||||
@ -99,12 +107,22 @@
|
||||
<h4 class="mb-5 d-flex align-items-center"><span class="d-inline-block lh-sm me-1" data-feather="link" style="height:16px;width:16px;"></span> {{ _("Related Records")}}</h4>
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<div class="mb-4">
|
||||
<div class="d-flex flex-wrap justify-content-between mb-2">
|
||||
<h5 class="mb-0 text-body-highlight me-2">{{ _("Lead") }}</h5>
|
||||
</div>
|
||||
{% if opportunity.lead %}
|
||||
<span class="badge rounded-pill bg-phoenix-primary text-primary"><a class="dropdown-item d-flex align-items-center" href="{% url 'lead_detail' opportunity.lead.slug %}" target="_blank">{{ _("View Lead")}}  <span class="d-inline-block lh-sm me-2" data-feather="external-link" style="height:16px;width:16px;"></span></a></span>
|
||||
{% else %}
|
||||
<p>{{ _("No Lead") }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="d-flex flex-wrap justify-content-between mb-2">
|
||||
<h5 class="mb-0 text-body-highlight me-2">{{ _("Estimate") }}</h5>
|
||||
</div>
|
||||
{% if opportunity.estimate %}
|
||||
<a class="dropdown-item" href="{% url 'estimate_detail' opportunity.estimate.pk %}">{{ _("View Quotation")}}</a>
|
||||
<span class="badge rounded-pill bg-phoenix-primary text-primary"><a class="dropdown-item" href="{% url 'estimate_detail' opportunity.estimate.pk %}">{{ _("View Quotation")}}</a></span>
|
||||
{% else %}
|
||||
<p>{{ _("No Estimate") }}</p>
|
||||
{% endif %}
|
||||
@ -114,7 +132,7 @@
|
||||
<h5 class="mb-0 text-body-highlight me-2">{{ _("Invoice") }}</h5>
|
||||
</div>
|
||||
{% if opportunity.estimate.invoice %}
|
||||
<a class="dropdown-item" href="{% url 'invoice_detail' opportunity.estimate.invoice.pk %}">{{ _("View Invoice")}}</a>
|
||||
<span class="badge rounded-pill bg-phoenix-primary text-primary"><a class="dropdown-item" href="{% url 'invoice_detail' opportunity.estimate.invoice.pk %}">{{ _("View Invoice")}}</a></span>
|
||||
{% else %}
|
||||
<p>{{ _("No Invoice") }}</p>
|
||||
{% endif %}
|
||||
@ -234,7 +252,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 d-none d-sm-block pe-sm-2">:</td>
|
||||
<td class="py-2"><a class="ps-6 ps-sm-0 fw-semibold mb-0 pb-3 pb-sm-0 text-body" href="tel:{{ opportunity.customer.phone_number }}">{{ opportunity.customer.phone_number }}</a></td>
|
||||
<td class="py-2"><a class="ps-6 ps-sm-0 fw-semibold mb-0 pb-3 pb-sm-0 text-body" href="tel:{{ opportunity.customer.phone_number }}">{{ opportunity.lead.phone_number }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="py-2">
|
||||
@ -244,7 +262,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 d-none d-sm-block pe-sm-2">:</td>
|
||||
<td class="py-2"><a class="ps-6 ps-sm-0 fw-semibold mb-0 text-body" href="mailto:{{ opportunity.customer.email}}">{{ opportunity.customer.email}}</a></td>
|
||||
<td class="py-2"><a class="ps-6 ps-sm-0 fw-semibold mb-0 text-body" href="mailto:{{ opportunity.customer.email}}">{{ opportunity.lead.email}}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@ -432,7 +450,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
{% for metting in opportunity.lead.get_meetings %}
|
||||
{% for metting in opportunity.get_meetings %}
|
||||
<div class="col-xxl-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
@ -454,12 +472,10 @@
|
||||
<div class="col-auto d-flex flex-1">
|
||||
<h2 class="mb-0">Call</h2>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<a href="{% url 'schedule_lead' opportunity.lead.slug %}" class="btn btn-primary"><span class="fa-solid fa-plus me-2"></span>Add Call</a>
|
||||
</div>
|
||||
</div>
|
||||
<pre>{{opportunity.get_all_notes}}</pre>
|
||||
<div class="border-top border-bottom border-translucent" id="leadDetailsTable" data-list='{"valueNames":["name","description","create_date","create_by","last_activity"],"page":5,"pagination":true}'>
|
||||
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||
<table class="table fs-9 mb-0">
|
||||
@ -471,7 +487,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="lead-details-table-body">
|
||||
{% for call in opportunity.lead.get_calls %}
|
||||
{% for call in opportunity.get_calls %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
<td class="description align-middle white-space-nowrap text-start fw-bold text-body-tertiary py-2 pe-6">{{call.purpose}}</td>
|
||||
<td class="create_date text-end align-middle white-space-nowrap text-body py-2">{{call.scheduled_by}}</td>
|
||||
@ -543,7 +559,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="all-email-table-body">
|
||||
{% for email in opportunity.lead.get_emails %}
|
||||
{% for email in opportunity.get_emails %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
<td class="fs-9 align-middle px-0 py-3">
|
||||
<div class="form-check mb-0 fs-8">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load i18n custom_filters %}
|
||||
{% block title %}{% trans "Accounts" %}{% endblock title %}
|
||||
{% block accounts %}
|
||||
<a class="nav-link active fw-bold">
|
||||
@ -8,120 +8,137 @@
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<!--test-->
|
||||
<div class="row mt-4">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<h3 class=""><i class="fa-solid fa-book"></i> {% trans "Accounts" %}</h3>
|
||||
<a href="{% url 'account_create' %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans 'New Account' %}</a>
|
||||
</div>
|
||||
{% include "partials/search_box.html" %}
|
||||
|
||||
{% if page_obj.object_list %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Type" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Account Name" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Code" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Balance Type" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Active" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list">
|
||||
{% for account in accounts %}
|
||||
<!-- Account Type Tabs -->
|
||||
<div class="mb-4">
|
||||
<ul class="nav nav-tabs" id="accountTypeTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="assets-tab" data-bs-toggle="tab" data-bs-target="#assets" type="button" role="tab" aria-controls="assets" aria-selected="true">
|
||||
<i class="fas fa-wallet me-2"></i>{% trans "Assets" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="cogs-tab" data-bs-toggle="tab" data-bs-target="#cogs" type="button" role="tab" aria-controls="cogs" aria-selected="false">
|
||||
<i class="fas fa-boxes me-2"></i>{% trans "COGS" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="capital-tab" data-bs-toggle="tab" data-bs-target="#capital" type="button" role="tab" aria-controls="capital" aria-selected="false">
|
||||
<i class="fas fa-landmark me-2"></i>{% trans "Capital" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="income-tab" data-bs-toggle="tab" data-bs-target="#income" type="button" role="tab" aria-controls="income" aria-selected="false">
|
||||
<i class="fas fa-money-bill-wave me-2"></i>{% trans "Income" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="expenses-tab" data-bs-toggle="tab" data-bs-target="#expenses" type="button" role="tab" aria-controls="expenses" aria-selected="false">
|
||||
<i class="fas fa-receipt me-2"></i>{% trans "Expenses" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="liabilities-tab" data-bs-toggle="tab" data-bs-target="#liabilities" type="button" role="tab" aria-controls="liabilities" aria-selected="false">
|
||||
<i class="fas fa-receipt me-2"></i>{% trans "Liabilities" %}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="modal fade" id="deleteModal"
|
||||
data-bs-backdrop="static"
|
||||
data-bs-keyboard="false"
|
||||
tabindex="-1"
|
||||
aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent">
|
||||
<!-- Assets Tab -->
|
||||
<div class="tab-pane fade show active" id="assets" role="tabpanel" aria-labelledby="assets-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% with accounts=accounts|filter_by_role:"ex_" %}
|
||||
{% include "ledger/coa_accounts/partials/account_table.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
{% trans "Delete Account" %}
|
||||
<span data-feather="alert-circle"></span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p class="mb-0 text-danger fw-bold">
|
||||
{% trans "Are you sure you want to delete this Account?" %}
|
||||
</p>
|
||||
<div class="d-grid gap-2">
|
||||
<button type="button" class="btn btn-phoenix-secondary btn-sm" data-bs-dismiss="modal">
|
||||
{% trans "No" %}
|
||||
</button>
|
||||
<a type="button" class="btn btn-phoenix-danger btn-sm" href="{% url 'account_delete' account.uuid %}">
|
||||
{% trans "Yes" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- COGS Tab -->
|
||||
<div class="tab-pane fade" id="cogs" role="tabpanel" aria-labelledby="cogs-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% with accounts=accounts|filter_by_role:"cogs" %}
|
||||
{% include "ledger/coa_accounts/partials/account_table.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Capital Tab -->
|
||||
<div class="tab-pane fade" id="capital" role="tabpanel" aria-labelledby="capital-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% with accounts=accounts|filter_by_role:"eq_" %}
|
||||
{% include "ledger/coa_accounts/partials/account_table.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{{ account.role_bs|upper }}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{{ account.name }}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{{ account.code }}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
<!-- Income Tab -->
|
||||
<div class="tab-pane fade" id="income" role="tabpanel" aria-labelledby="income-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% with accounts=accounts|filter_by_role:"in_" %}
|
||||
{% include "ledger/coa_accounts/partials/account_table.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
{% if account.balance_type == 'debit' %}
|
||||
<div class="badge badge-phoenix fs-10 badge-phoenix-success"><span class="fw-bold"><i class="fa-solid fa-circle-up"></i> {{ _("Debit") }}</span></div>
|
||||
{% else %}
|
||||
<div class="badge badge-phoenix fs-10 badge-phoenix-danger"><span class="fw-bold"><i class="fa-solid fa-circle-down"></i> {{ _("Credit") }}</span></div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if account.active %}
|
||||
<span class="fw-bold text-success fas fa-check-circle"></span>
|
||||
{% else %}
|
||||
<span class="fw-bold text-danger far fa-times-circle"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-start">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2"><a href="{% url 'account_detail' account.uuid %}" class="dropdown-item text-success-dark">
|
||||
{% trans "View" %}
|
||||
</a>
|
||||
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted">{% trans "No Accounts Found" %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- Expenses Tab -->
|
||||
<div class="tab-pane fade" id="expenses" role="tabpanel" aria-labelledby="expenses-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% with accounts=accounts|filter_by_role:"ex_" %}
|
||||
{% include "ledger/coa_accounts/partials/account_table.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
<!-- Liabilities Tab -->
|
||||
<div class="tab-pane fade" id="liabilities" role="tabpanel" aria-labelledby="liabilities-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% with accounts=accounts|filter_by_role:"lia_" %}
|
||||
{% include "ledger/coa_accounts/partials/account_table.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
{% if is_paginated %}
|
||||
{% include 'partials/pagination.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<!--test-->
|
||||
|
||||
<!-- Delete Modal (moved outside tables) -->
|
||||
<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
{% trans "Delete Account" %}
|
||||
<span data-feather="alert-circle"></span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p class="mb-0 text-danger fw-bold">
|
||||
{% trans "Are you sure you want to delete this Account?" %}
|
||||
</p>
|
||||
<div class="d-grid gap-2">
|
||||
<button type="button" class="btn btn-phoenix-secondary btn-sm" data-bs-dismiss="modal">
|
||||
{% trans "No" %}
|
||||
</button>
|
||||
<a id="deleteAccountBtn" type="button" class="btn btn-phoenix-danger btn-sm" href="#">
|
||||
{% trans "Yes" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block customerJS %}
|
||||
<script>
|
||||
// Handle delete modal for all tables
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var deleteModal = document.getElementById('deleteModal');
|
||||
deleteModal.addEventListener('show.bs.modal', function(event) {
|
||||
var button = event.relatedTarget;
|
||||
var accountId = button.closest('tr').getAttribute('data-account-id');
|
||||
document.getElementById('deleteAccountBtn').href = `/accounts/delete/${accountId}/`;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
69
templates/ledger/coa_accounts/partials/account_table.html
Normal file
69
templates/ledger/coa_accounts/partials/account_table.html
Normal file
@ -0,0 +1,69 @@
|
||||
{% load i18n %}
|
||||
{% if accounts %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Account Name" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Code" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Balance Type" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{% trans "Active" %}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list">
|
||||
{% for account in accounts %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static" data-account-id="{{ account.uuid }}">
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{{ account.name }}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{{ account.code }}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if account.balance_type == 'debit' %}
|
||||
<div class="badge badge-phoenix fs-10 badge-phoenix-success"><span class="fw-bold"><i class="fa-solid fa-circle-up"></i> {{ _("Debit") }}</span></div>
|
||||
{% else %}
|
||||
<div class="badge badge-phoenix fs-10 badge-phoenix-danger"><span class="fw-bold"><i class="fa-solid fa-circle-down"></i> {{ _("Credit") }}</span></div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if account.active %}
|
||||
<span class="fw-bold text-success fas fa-check-circle"></span>
|
||||
{% else %}
|
||||
<span class="fw-bold text-danger far fa-times-circle"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap text-start">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a href="{% url 'account_detail' account.uuid %}" class="dropdown-item text-success-dark">
|
||||
{% trans "View" %}
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted">{% trans "No Accounts Found" %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
{% if is_paginated %}
|
||||
{% include 'partials/pagination.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert ">
|
||||
{% trans "No accounts found in this category." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
Loading…
x
Reference in New Issue
Block a user