Add demo script
@@ -339,4 +339,25 @@ test-sao:
|
|||||||
PACKAGE: sao
|
PACKAGE: sao
|
||||||
TAG_PATTERN: '/^sao-.*/'
|
TAG_PATTERN: '/^sao-.*/'
|
||||||
|
|
||||||
|
test-demo:
|
||||||
|
stage: test
|
||||||
|
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/python:3.8
|
||||||
|
variables:
|
||||||
|
TRYTOND_DATABASE__PATH: /tmp
|
||||||
|
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- .cache/pip/http
|
||||||
|
before_script:
|
||||||
|
- pip install packages/trytond* packages/proteus*
|
||||||
|
script:
|
||||||
|
- touch /tmp/demo.sqlite
|
||||||
|
- echo "admin" > /tmp/password
|
||||||
|
- TRYTONPASSFILE=/tmp/password trytond-admin --database demo --all --email admin@example.com
|
||||||
|
- python -m demo --database demo
|
||||||
|
rules:
|
||||||
|
- changes:
|
||||||
|
- demo/**/*
|
||||||
|
- modules/{account,account_invoice,account_payment,account_statement,company,country,currency,party,product,production,production_routing,production_work,project,purchase,sale,stock,timesheet}/**/*
|
||||||
|
|
||||||
include: '.gitlab-ci-modules.yml'
|
include: '.gitlab-ci-modules.yml'
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
|
||||||
|
|
||||||
|
from proteus import Model, Wizard
|
||||||
|
from proteus import config as pconfig
|
||||||
|
|
||||||
|
from . import account, account_invoice, account_payment, account_statement
|
||||||
|
from . import company as company_
|
||||||
|
from . import (
|
||||||
|
country, currency, party, product, production, project, purchase, sale,
|
||||||
|
stock, timesheet)
|
||||||
|
|
||||||
|
|
||||||
|
def set_config(database, config_file):
|
||||||
|
return pconfig.set_trytond(database, config_file=config_file)
|
||||||
|
|
||||||
|
|
||||||
|
def activate_modules(config, modules):
|
||||||
|
Module = Model.get('ir.module')
|
||||||
|
modules = Module.find([
|
||||||
|
('name', 'in', modules),
|
||||||
|
])
|
||||||
|
for module in modules:
|
||||||
|
if module.state == 'activated':
|
||||||
|
module.click('upgrade')
|
||||||
|
else:
|
||||||
|
module.click('activate')
|
||||||
|
modules = [x.name for x in Module.find([('state', '=', 'to activate')])]
|
||||||
|
Wizard('ir.module.activate_upgrade').execute('upgrade')
|
||||||
|
|
||||||
|
ConfigWizardItem = Model.get('ir.module.config_wizard.item')
|
||||||
|
for item in ConfigWizardItem.find([('state', '!=', 'done')]):
|
||||||
|
item.state = 'done'
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
activated_modules = [m.name
|
||||||
|
for m in Module.find([('state', '=', 'activated')])]
|
||||||
|
return modules, activated_modules
|
||||||
|
|
||||||
|
|
||||||
|
def setup_languages(config, demo_password, company=None):
|
||||||
|
Lang = Model.get('ir.lang')
|
||||||
|
User = Model.get('res.user')
|
||||||
|
Group = Model.get('res.group')
|
||||||
|
Action = Model.get('ir.action')
|
||||||
|
|
||||||
|
langs = Lang.find()
|
||||||
|
Lang.click(langs, 'load_translations')
|
||||||
|
|
||||||
|
admin = config.user
|
||||||
|
# Use root to skip password validation
|
||||||
|
config.user = 0
|
||||||
|
|
||||||
|
menu, = Action.find([('usage', '=', 'menu')])
|
||||||
|
for lang in langs:
|
||||||
|
if lang.code == 'en':
|
||||||
|
name = 'Demo'
|
||||||
|
login = 'demo'
|
||||||
|
else:
|
||||||
|
if lang.code[:2] != lang.code[-2:].lower():
|
||||||
|
continue
|
||||||
|
name = 'Demo %s' % lang.name
|
||||||
|
login = 'demo_%s' % lang.code[:2]
|
||||||
|
try:
|
||||||
|
user, = User.find([('login', '=', login)])
|
||||||
|
except ValueError:
|
||||||
|
user = User()
|
||||||
|
user.name = name
|
||||||
|
user.login = login
|
||||||
|
user.password = demo_password
|
||||||
|
groups = Group.find([
|
||||||
|
('name', 'not ilike', '%Admin%'),
|
||||||
|
])
|
||||||
|
user.groups.extend(groups)
|
||||||
|
user.language = lang
|
||||||
|
user.menu = menu
|
||||||
|
if company:
|
||||||
|
Company = Model.get('company.company')
|
||||||
|
user.companies.append(Company(company.id))
|
||||||
|
user.company = company
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
config.user = admin
|
||||||
|
|
||||||
|
|
||||||
|
def main(database, modules, demo_password, config_file=None):
|
||||||
|
config = set_config(database, config_file)
|
||||||
|
to_activate, activated = activate_modules(config, modules)
|
||||||
|
|
||||||
|
if 'country' in to_activate:
|
||||||
|
country.do_import()
|
||||||
|
|
||||||
|
if 'currency' in to_activate:
|
||||||
|
currency.do_import()
|
||||||
|
|
||||||
|
if ('party' in to_activate
|
||||||
|
or 'sale' in to_activate
|
||||||
|
or 'purchase' in to_activate
|
||||||
|
or 'stock' in activated):
|
||||||
|
customers, suppliers = party.setup(config, modules)
|
||||||
|
|
||||||
|
if 'company' in to_activate:
|
||||||
|
company = company_.setup(config, activated)
|
||||||
|
elif 'company' in activated:
|
||||||
|
company = company.get()
|
||||||
|
else:
|
||||||
|
company = None
|
||||||
|
|
||||||
|
if 'account' in to_activate:
|
||||||
|
account.setup(config, activated, company)
|
||||||
|
|
||||||
|
if 'company' in to_activate:
|
||||||
|
company_.setup_post(config, activated, company)
|
||||||
|
|
||||||
|
if 'product' in to_activate:
|
||||||
|
product.setup(config, activated, company=company)
|
||||||
|
|
||||||
|
if 'account_invoice' in to_activate:
|
||||||
|
account_invoice.setup(config, activated, company)
|
||||||
|
|
||||||
|
if 'sale' in to_activate:
|
||||||
|
sale.setup(config, activated, company, customers)
|
||||||
|
|
||||||
|
if 'purchase' in to_activate:
|
||||||
|
purchase.setup(config, activated, company, suppliers)
|
||||||
|
|
||||||
|
if 'stock' in to_activate:
|
||||||
|
stock.setup(config, activated, company, suppliers)
|
||||||
|
|
||||||
|
if 'account_invoice' in activated:
|
||||||
|
account_invoice.setup_post(config, activated, company)
|
||||||
|
|
||||||
|
if 'account_payment' in activated:
|
||||||
|
account_payment.setup(config, activated, company)
|
||||||
|
|
||||||
|
if 'account_statement' in activated:
|
||||||
|
account_statement.setup(config, activated, company)
|
||||||
|
|
||||||
|
if 'project' in activated:
|
||||||
|
project.setup(config, activated, company, customers)
|
||||||
|
|
||||||
|
if 'timesheet' in activated:
|
||||||
|
timesheet.setup(config, activated, company)
|
||||||
|
|
||||||
|
if 'production' in to_activate:
|
||||||
|
production.setup(config, activated, company)
|
||||||
|
|
||||||
|
setup_languages(config, demo_password, company=company)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
||||||
|
parser.add_argument('-c', '--config', dest='config_file')
|
||||||
|
parser.add_argument('-m', '--module', dest='modules', nargs='+',
|
||||||
|
help='module to activate', default=[
|
||||||
|
'account',
|
||||||
|
'account_invoice',
|
||||||
|
'account_payment',
|
||||||
|
'account_statement',
|
||||||
|
'company',
|
||||||
|
'party',
|
||||||
|
'party_avatar',
|
||||||
|
'product',
|
||||||
|
'purchase',
|
||||||
|
'sale',
|
||||||
|
'stock',
|
||||||
|
'project',
|
||||||
|
'timesheet',
|
||||||
|
'production',
|
||||||
|
'production_routing',
|
||||||
|
'production_work',
|
||||||
|
])
|
||||||
|
parser.add_argument('--demo_password', dest='demo_password',
|
||||||
|
default='demo', help='demo password')
|
||||||
|
parser.add_argument('-d', '--database', dest='database',
|
||||||
|
default='demo', help="database name")
|
||||||
|
options = parser.parse_args()
|
||||||
|
main(options.database, options.modules, options.demo_password,
|
||||||
|
config_file=options.config_file)
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model, Wizard
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company):
|
||||||
|
AccountTemplate = Model.get('account.account.template')
|
||||||
|
Account = Model.get('account.account')
|
||||||
|
FiscalYear = Model.get('account.fiscalyear')
|
||||||
|
Sequence = Model.get('ir.sequence')
|
||||||
|
SequenceStrict = Model.get('ir.sequence.strict')
|
||||||
|
SequenceType = Model.get('ir.sequence.type')
|
||||||
|
Party = Model.get('party.party')
|
||||||
|
|
||||||
|
root_template, = AccountTemplate.find([
|
||||||
|
('parent', '=', None),
|
||||||
|
('name', '=', 'Minimal Account Chart'),
|
||||||
|
])
|
||||||
|
create_chart_account = Wizard('account.create_chart')
|
||||||
|
create_chart_account.execute('account')
|
||||||
|
create_chart_account.form.account_template = root_template
|
||||||
|
create_chart_account.form.company = company
|
||||||
|
create_chart_account.execute('create_account')
|
||||||
|
|
||||||
|
receivable, = Account.find([
|
||||||
|
('type.receivable', '=', True),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
payable, = Account.find([
|
||||||
|
('type.payable', '=', True),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
|
||||||
|
create_chart_account.form.account_receivable = receivable
|
||||||
|
create_chart_account.form.account_payable = payable
|
||||||
|
create_chart_account.execute('create_properties')
|
||||||
|
|
||||||
|
# Set account for parties created without company
|
||||||
|
parties = Party.find([])
|
||||||
|
for party in parties:
|
||||||
|
party.account_receivable = receivable
|
||||||
|
party.account_payable = payable
|
||||||
|
Party.save(parties)
|
||||||
|
|
||||||
|
move_sequence_type, = SequenceType.find(
|
||||||
|
[('name', '=', "Account Move")], limit=1)
|
||||||
|
invoice_sequence_type, = SequenceType.find([
|
||||||
|
('name', '=', "Invoice"),
|
||||||
|
], limit=1)
|
||||||
|
today = dt.date.today()
|
||||||
|
for start_date in (
|
||||||
|
today + relativedelta(month=1, day=1, years=-1),
|
||||||
|
today + relativedelta(month=1, day=1),
|
||||||
|
today + relativedelta(month=1, day=1, years=1)):
|
||||||
|
fiscalyear = FiscalYear(name='%s' % start_date.year)
|
||||||
|
fiscalyear.start_date = start_date
|
||||||
|
fiscalyear.end_date = start_date + relativedelta(month=12, day=31)
|
||||||
|
fiscalyear.company = company
|
||||||
|
post_move_sequence = Sequence(name='%s' % start_date.year,
|
||||||
|
sequence_type=move_sequence_type,
|
||||||
|
company=company)
|
||||||
|
post_move_sequence.save()
|
||||||
|
fiscalyear.post_move_sequence = post_move_sequence
|
||||||
|
invoice_sequence, = fiscalyear.invoice_sequences
|
||||||
|
if 'account_invoice' in modules:
|
||||||
|
for attr, name in (('out_invoice_sequence', 'Invoice'),
|
||||||
|
('in_invoice_sequence', 'Supplier Invoice'),
|
||||||
|
('out_credit_note_sequence', 'Credit Note'),
|
||||||
|
('in_credit_note_sequence', 'Supplier Credit Note')):
|
||||||
|
sequence = SequenceStrict(
|
||||||
|
name='%s %s' % (name, start_date.year),
|
||||||
|
sequence_type=invoice_sequence_type,
|
||||||
|
company=company)
|
||||||
|
sequence.save()
|
||||||
|
setattr(invoice_sequence, attr, sequence)
|
||||||
|
fiscalyear.save()
|
||||||
|
fiscalyear.click('create_period')
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import random
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
from .tools import skip_warning
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company):
|
||||||
|
Party = Model.get('party.party')
|
||||||
|
PaymentTerm = Model.get('account.invoice.payment_term')
|
||||||
|
|
||||||
|
payment_term = PaymentTerm(name='30 days')
|
||||||
|
line = payment_term.lines.new()
|
||||||
|
line.type = 'remainder'
|
||||||
|
delta = line.relativedeltas.new()
|
||||||
|
delta.days = 30
|
||||||
|
payment_term.save()
|
||||||
|
|
||||||
|
parties = Party.find()
|
||||||
|
Party.write([p.id for p in parties], {
|
||||||
|
'customer_payment_term': payment_term.id,
|
||||||
|
'supplier_payment_term': payment_term.id,
|
||||||
|
}, config.context)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_post(config, modules, company):
|
||||||
|
Invoice = Model.get('account.invoice')
|
||||||
|
|
||||||
|
invoices = Invoice.find([
|
||||||
|
('type', '=', 'out'),
|
||||||
|
('state', 'in', ['draft', 'validated']),
|
||||||
|
])
|
||||||
|
invoices = random.sample(invoices, len(invoices) * 2 // 3)
|
||||||
|
invoices = list(chain(*list(zip(invoices,
|
||||||
|
Invoice.find([
|
||||||
|
('type', '=', 'in'),
|
||||||
|
('state', 'in', ['draft', 'validated']),
|
||||||
|
])))))
|
||||||
|
|
||||||
|
today = dt.date.today()
|
||||||
|
invoice_date = today + relativedelta(months=-1)
|
||||||
|
i = j = 0
|
||||||
|
while invoice_date <= today:
|
||||||
|
j = random.randint(1, 5)
|
||||||
|
for invoice in invoices[i:i + j]:
|
||||||
|
invoice.invoice_date = invoice_date
|
||||||
|
invoice.save()
|
||||||
|
i += j
|
||||||
|
invoice_date += relativedelta(days=random.randint(1, 3))
|
||||||
|
invoices = [inv for inv in invoices[0:i]]
|
||||||
|
for invoice in invoices:
|
||||||
|
skip_warning(config, 'invoice_payment_term', [invoice])
|
||||||
|
skip_warning(config, 'invoice_date_future', invoices)
|
||||||
|
Invoice.click(invoices, 'post')
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
from proteus import Model, Wizard
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company):
|
||||||
|
Currency = Model.get('currency.currency')
|
||||||
|
Journal = Model.get('account.payment.journal')
|
||||||
|
Line = Model.get('account.move.line')
|
||||||
|
Payment = Model.get('account.payment')
|
||||||
|
|
||||||
|
usd, = Currency.find([('code', '=', 'USD')])
|
||||||
|
journal = Journal(name='Manual', currency=usd, company=company,
|
||||||
|
process_method='manual')
|
||||||
|
journal.save()
|
||||||
|
|
||||||
|
lines = Line.find([
|
||||||
|
('account.type.payable', '=', True),
|
||||||
|
('party', '!=', None),
|
||||||
|
('reconciliation', '=', None),
|
||||||
|
('payment_amount', '!=', 0),
|
||||||
|
])
|
||||||
|
lines = random.sample(lines, len(lines) * 2 // 3)
|
||||||
|
if not lines:
|
||||||
|
return
|
||||||
|
|
||||||
|
pay_line = Wizard('account.move.line.pay', lines)
|
||||||
|
pay_line.execute('next_')
|
||||||
|
pay_line.form.journal = journal
|
||||||
|
pay_line.execute('next_')
|
||||||
|
|
||||||
|
payments = Payment.find([])
|
||||||
|
payments = random.sample(payments, len(payments) * 2 // 3)
|
||||||
|
|
||||||
|
for payment in payments:
|
||||||
|
payment.click('approve')
|
||||||
|
|
||||||
|
payments = random.sample(payments, len(payments) * 2 // 3)
|
||||||
|
i = j = 0
|
||||||
|
while i < len(payments):
|
||||||
|
j = random.randint(1, 5)
|
||||||
|
Wizard('account.payment.process', payments[i:i + j])
|
||||||
|
i += j
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import random
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company):
|
||||||
|
Journal = Model.get('account.statement.journal')
|
||||||
|
Statement = Model.get('account.statement')
|
||||||
|
AccountJournal = Model.get('account.journal')
|
||||||
|
Account = Model.get('account.account')
|
||||||
|
Sequence = Model.get('ir.sequence')
|
||||||
|
SequenceType = Model.get('ir.sequence.type')
|
||||||
|
Invoice = Model.get('account.invoice')
|
||||||
|
|
||||||
|
sequence_type, = SequenceType.find([('name', '=', "Account Journal")])
|
||||||
|
sequence = Sequence(name='Statement',
|
||||||
|
sequence_type=sequence_type,
|
||||||
|
company=company)
|
||||||
|
sequence.save()
|
||||||
|
|
||||||
|
cash, = Account.find([
|
||||||
|
('name', '=', 'Main Cash'),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
|
||||||
|
account_journal = AccountJournal(name='Bank',
|
||||||
|
type='statement',
|
||||||
|
sequence=sequence)
|
||||||
|
account_journal.save()
|
||||||
|
|
||||||
|
journal = Journal(name='Bank',
|
||||||
|
journal=account_journal,
|
||||||
|
account=cash,
|
||||||
|
validation='balance')
|
||||||
|
journal.save()
|
||||||
|
|
||||||
|
invoices = Invoice.find([
|
||||||
|
('state', '=', 'posted'),
|
||||||
|
])
|
||||||
|
invoices = random.sample(invoices, len(invoices) * 2 // 3)
|
||||||
|
|
||||||
|
total_amount = Decimal(0)
|
||||||
|
statement = Statement(name='001',
|
||||||
|
journal=journal,
|
||||||
|
start_balance=Decimal(0))
|
||||||
|
for i, invoice in enumerate(invoices):
|
||||||
|
if not invoice.amount_to_pay:
|
||||||
|
continue
|
||||||
|
line = statement.lines.new()
|
||||||
|
line.number = str(i)
|
||||||
|
line.date = invoice.invoice_date + relativedelta(
|
||||||
|
days=random.randint(1, 20))
|
||||||
|
amount = invoice.amount_to_pay
|
||||||
|
if invoice.type in ('in_invoice', 'out_credit_note'):
|
||||||
|
amount = - amount
|
||||||
|
line.amount = amount
|
||||||
|
line.party = invoice.party
|
||||||
|
if random.random() < 2. / 3.:
|
||||||
|
line.related_to = invoice
|
||||||
|
total_amount += line.amount
|
||||||
|
|
||||||
|
statement.end_balance = total_amount
|
||||||
|
statement.click('validate_statement')
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
_AVATAR_DIR = os.path.join(os.path.dirname(__file__), 'avatars')
|
||||||
|
|
||||||
|
|
||||||
|
def get(name):
|
||||||
|
with open(os.path.join(_AVATAR_DIR, name), 'rb') as fp:
|
||||||
|
return fp.read()
|
||||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,134 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from proteus import Model, Wizard
|
||||||
|
|
||||||
|
from . import avatar
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules):
|
||||||
|
Party = Model.get('party.party')
|
||||||
|
Company = Model.get('company.company')
|
||||||
|
Currency = Model.get('currency.currency')
|
||||||
|
|
||||||
|
usd, = Currency.find([('code', '=', 'USD')])
|
||||||
|
rate = usd.rates.new()
|
||||||
|
rate.date = dt.date(dt.date.today().year, 1, 1)
|
||||||
|
rate.rate = Decimal('1')
|
||||||
|
usd.save()
|
||||||
|
|
||||||
|
company_config = Wizard('company.company.config')
|
||||||
|
company_config.execute('company')
|
||||||
|
company = company_config.form
|
||||||
|
party = Party(name='Michael Scott Paper Company')
|
||||||
|
if 'party_avatar' in modules:
|
||||||
|
party.avatar = avatar.get('michael-scott-paper-inc.jpg')
|
||||||
|
party.save()
|
||||||
|
company.party = party
|
||||||
|
company.currency = usd
|
||||||
|
company_config.execute('add')
|
||||||
|
|
||||||
|
# Reload context
|
||||||
|
User = Model.get('res.user')
|
||||||
|
config._context = User.get_preferences(True, {})
|
||||||
|
|
||||||
|
company, = Company.find()
|
||||||
|
return company
|
||||||
|
|
||||||
|
|
||||||
|
def setup_post(config, modules, company):
|
||||||
|
Party = Model.get('party.party')
|
||||||
|
Company = Model.get('company.company')
|
||||||
|
Currency = Model.get('currency.currency')
|
||||||
|
Address = Model.get('party.address')
|
||||||
|
Country = Model.get('country.country')
|
||||||
|
Subdivision = Model.get('country.subdivision')
|
||||||
|
Employee = Model.get('company.employee')
|
||||||
|
|
||||||
|
party_avatar = 'party_avatar' in modules
|
||||||
|
|
||||||
|
usd, = Currency.find([('code', '=', 'USD')])
|
||||||
|
try:
|
||||||
|
us, = Country.find([('code', '=', 'US')])
|
||||||
|
except ValueError:
|
||||||
|
us = None
|
||||||
|
|
||||||
|
party_scott = Party(name='Michael Scott')
|
||||||
|
if party_avatar:
|
||||||
|
party_scott.avatar = avatar.get('michael-scott.jpg')
|
||||||
|
party_scott.save()
|
||||||
|
Employee(party=party_scott, company=company).save()
|
||||||
|
party_beesly = Party(name='Pam Beesly')
|
||||||
|
if party_avatar:
|
||||||
|
party_beesly.avatar = avatar.get('pam-beesly.jpg')
|
||||||
|
party_beesly.save()
|
||||||
|
Employee(party=party_beesly, company=company).save()
|
||||||
|
party_howard = Party(name='Ryan Howard')
|
||||||
|
if party_avatar:
|
||||||
|
party_howard.avatar = avatar.get('ryan-howard.jpg')
|
||||||
|
party_howard.save()
|
||||||
|
Employee(party=party_howard, company=company).save()
|
||||||
|
|
||||||
|
dmi = Company()
|
||||||
|
party_dmi = Party(name='Dunder Mifflin inc')
|
||||||
|
address = Address()
|
||||||
|
party_dmi.addresses.append(address)
|
||||||
|
address.city = 'New York'
|
||||||
|
address.country = us
|
||||||
|
try:
|
||||||
|
address.subdivision, = Subdivision.find([('code', '=', 'US-NY')])
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
if party_avatar:
|
||||||
|
party_dmi.avatar = avatar.get('dunder-mifflin.jpg')
|
||||||
|
party_dmi.save()
|
||||||
|
dmi.party = party_dmi
|
||||||
|
dmi.currency = usd
|
||||||
|
dmi.save()
|
||||||
|
|
||||||
|
dms = Company()
|
||||||
|
party_dms = Party(name='Dunder Mifflin Scranton')
|
||||||
|
address = Address()
|
||||||
|
party_dms.addresses.append(address)
|
||||||
|
address.city = 'Scranton'
|
||||||
|
address.country = us
|
||||||
|
try:
|
||||||
|
address.subdivision, = Subdivision.find([('code', '=', 'US-PA')])
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
party_dms.save()
|
||||||
|
dms.party = party_dms
|
||||||
|
dms.currency = usd
|
||||||
|
dms.save()
|
||||||
|
|
||||||
|
party_halper = Party(name='Jim Halper')
|
||||||
|
if party_avatar:
|
||||||
|
party_halper.avatar = avatar.get('jim-halper.jpg')
|
||||||
|
party_halper.save()
|
||||||
|
Employee(party=party_halper, company=dms).save()
|
||||||
|
party_schrute = Party(name='Dwight Schrute')
|
||||||
|
if party_avatar:
|
||||||
|
party_schrute.avatar = avatar.get('dwight-schrute.jpg')
|
||||||
|
party_schrute.save()
|
||||||
|
Employee(party=party_schrute, company=dms).save()
|
||||||
|
party_martin = Party(name='Angela Martin')
|
||||||
|
if party_avatar:
|
||||||
|
party_martin.avatar = avatar.get('angela-martin.jpg')
|
||||||
|
party_martin.save()
|
||||||
|
Employee(party=party_martin, company=dms).save()
|
||||||
|
party_miner = Party(name='Charles Miner')
|
||||||
|
if party_avatar:
|
||||||
|
party_miner.avatar = avatar.get('charles-miner.jpg')
|
||||||
|
party_miner.save()
|
||||||
|
Employee(party=party_miner, company=dms).save()
|
||||||
|
|
||||||
|
|
||||||
|
def get():
|
||||||
|
Company = Model.get('company.company')
|
||||||
|
company, = Company.find([
|
||||||
|
('party.name', '=', 'Michael Scott Paper Company'),
|
||||||
|
])
|
||||||
|
return company
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
try:
|
||||||
|
from trytond.modules.country.scripts.import_countries import do_import
|
||||||
|
except ImportError:
|
||||||
|
def do_import(*args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
__all__ = [do_import]
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
try:
|
||||||
|
from trytond.modules.currency.scripts.import_currencies import do_import
|
||||||
|
except ImportError:
|
||||||
|
def do_import(*args, **kwargs):
|
||||||
|
Currency = Model.get('currency.currency')
|
||||||
|
usd = Currency(name="USD", code='USD')
|
||||||
|
usd.save()
|
||||||
|
|
||||||
|
__all__ = [do_import]
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
from . import avatar
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules):
|
||||||
|
Party = Model.get('party.party')
|
||||||
|
Address = Model.get('party.address')
|
||||||
|
Country = Model.get('country.country')
|
||||||
|
Subdivision = Model.get('country.subdivision')
|
||||||
|
ContactMechanism = Model.get('party.contact_mechanism')
|
||||||
|
|
||||||
|
customers, suppliers = [], []
|
||||||
|
|
||||||
|
try:
|
||||||
|
us, = Country.find([('code', '=', 'US')])
|
||||||
|
except ValueError:
|
||||||
|
us = None
|
||||||
|
try:
|
||||||
|
pennsylvania, = Subdivision.find([('code', '=', 'US-PA')])
|
||||||
|
except ValueError:
|
||||||
|
pennsylvania = None
|
||||||
|
|
||||||
|
name = 'Electric City Trolley Museum Association'
|
||||||
|
try:
|
||||||
|
party, = Party.find([('name', '=', name)])
|
||||||
|
except ValueError:
|
||||||
|
party = Party(name=name)
|
||||||
|
party.addresses.pop()
|
||||||
|
party.addresses.append(Address(street='300 Cliff Street',
|
||||||
|
postal_code='18503', city='Scranton', country=us,
|
||||||
|
subdivision=pennsylvania))
|
||||||
|
party.contact_mechanisms.append(ContactMechanism(type='phone',
|
||||||
|
value='+1 570-963-6590'))
|
||||||
|
party.contact_mechanisms.append(ContactMechanism(type='website',
|
||||||
|
value='http://www.ectma.org/'))
|
||||||
|
party.save()
|
||||||
|
customers.append(party)
|
||||||
|
|
||||||
|
name = 'Albright Memorial Library'
|
||||||
|
try:
|
||||||
|
party, = Party.find([('name', '=', name)])
|
||||||
|
except ValueError:
|
||||||
|
party = Party(name=name)
|
||||||
|
party.addresses.pop()
|
||||||
|
party.addresses.append(Address(street='500 Vine Street',
|
||||||
|
postal_code='18509', city='Scranton', country=us,
|
||||||
|
subdivision=pennsylvania))
|
||||||
|
party.contact_mechanisms.append(ContactMechanism(type='phone',
|
||||||
|
value='+1 570-348-3000'))
|
||||||
|
party.contact_mechanisms.append(ContactMechanism(type='website',
|
||||||
|
value='http://www.albright.org/'))
|
||||||
|
party.save()
|
||||||
|
customers.append(party)
|
||||||
|
|
||||||
|
name = "Cooper's Seafood House"
|
||||||
|
try:
|
||||||
|
party, = Party.find([('name', '=', name)])
|
||||||
|
except ValueError:
|
||||||
|
party = Party(name=name)
|
||||||
|
party.addresses.pop()
|
||||||
|
party.addresses.append(Address(street='701 North Washington Avenue',
|
||||||
|
postal_code='18509', city='Scranton', country=us,
|
||||||
|
subdivision=pennsylvania))
|
||||||
|
party.contact_mechanisms.append(ContactMechanism(type='phone',
|
||||||
|
value='+1 570-346-6883'))
|
||||||
|
party.save()
|
||||||
|
customers.append(party)
|
||||||
|
|
||||||
|
name = "Saber"
|
||||||
|
try:
|
||||||
|
party, = Party.find([('name', '=', name)])
|
||||||
|
except ValueError:
|
||||||
|
party = Party(name=name)
|
||||||
|
if 'party_avatar' in modules:
|
||||||
|
party.avatar = avatar.get('saber.jpg')
|
||||||
|
party.save()
|
||||||
|
suppliers.append(party)
|
||||||
|
|
||||||
|
return customers, suppliers
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company=None):
|
||||||
|
ProductTemplate = Model.get('product.template')
|
||||||
|
Category = Model.get('product.category')
|
||||||
|
Uom = Model.get('product.uom')
|
||||||
|
|
||||||
|
if 'account_product' in modules:
|
||||||
|
Account = Model.get('account.account')
|
||||||
|
expense, = Account.find([
|
||||||
|
('type.expense', '=', True),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
revenue, = Account.find([
|
||||||
|
('type.revenue', '=', True),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
account_category = Category(name="Papers", accounting=True)
|
||||||
|
account_category.account_expense = expense
|
||||||
|
account_category.account_revenue = revenue
|
||||||
|
account_category.save()
|
||||||
|
|
||||||
|
papers = Category(name='Papers')
|
||||||
|
papers.save()
|
||||||
|
|
||||||
|
sizes = {}
|
||||||
|
for format in ['A5', 'A4', 'A3', 'Letter', 'Legal', 'Ledger']:
|
||||||
|
size = Category(name=format, parent=papers)
|
||||||
|
if 'account_product' in modules:
|
||||||
|
size.account_expense = expense
|
||||||
|
size.account_revenue = revenue
|
||||||
|
size.save()
|
||||||
|
sizes[format] = size
|
||||||
|
|
||||||
|
unit, = Uom.find([('name', '=', 'Unit')])
|
||||||
|
|
||||||
|
margin = Decimal('1.01')
|
||||||
|
for quantity in [250, 500]:
|
||||||
|
for format, category in sizes.items():
|
||||||
|
paper_template = ProductTemplate(name='%s Paper %s'
|
||||||
|
% (format, quantity))
|
||||||
|
paper_template.categories.append(Category(category.id))
|
||||||
|
if 'account_product' in modules:
|
||||||
|
paper_template.account_category = account_category
|
||||||
|
paper_template.default_uom = unit
|
||||||
|
paper_template.type = 'goods'
|
||||||
|
paper_template.list_price = (Decimal('0.02') * quantity * margin
|
||||||
|
).quantize(Decimal('0.0001'))
|
||||||
|
paper, = paper_template.products
|
||||||
|
paper.cost_price = Decimal('0.01') * quantity
|
||||||
|
if 'sale' in modules:
|
||||||
|
paper_template.salable = True
|
||||||
|
if 'purchase' in modules:
|
||||||
|
paper_template.purchasable = True
|
||||||
|
paper_template.save()
|
||||||
|
margin *= margin
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import random
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, activated, company):
|
||||||
|
BOM = Model.get('production.bom')
|
||||||
|
Production = Model.get('production')
|
||||||
|
ProductTemplate = Model.get('product.template')
|
||||||
|
Category = Model.get('product.category')
|
||||||
|
Uom = Model.get('product.uom')
|
||||||
|
|
||||||
|
unit, = Uom.find([('name', '=', 'Unit')])
|
||||||
|
|
||||||
|
if 'account_product' in activated:
|
||||||
|
Account = Model.get('account.account')
|
||||||
|
expense, = Account.find([
|
||||||
|
('type.expense', '=', True),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
revenue, = Account.find([
|
||||||
|
('type.revenue', '=', True),
|
||||||
|
('company', '=', company.id),
|
||||||
|
])
|
||||||
|
account_category = Category(name="Computers", accounting=True)
|
||||||
|
account_category.account_expense = expense
|
||||||
|
account_category.account_revenue = revenue
|
||||||
|
account_category.save()
|
||||||
|
|
||||||
|
def create_product(name, list_price, cost_price):
|
||||||
|
template = ProductTemplate(name=name)
|
||||||
|
template.default_uom = unit
|
||||||
|
template.type = 'goods'
|
||||||
|
template.list_price = list_price
|
||||||
|
template.cost_price = cost_price
|
||||||
|
if 'account_product' in activated:
|
||||||
|
template.account_category = account_category
|
||||||
|
template.save()
|
||||||
|
return template.products[0]
|
||||||
|
|
||||||
|
bom = BOM(name='Computer rev1')
|
||||||
|
|
||||||
|
input_ = bom.inputs.new()
|
||||||
|
tower = create_product('Tower', Decimal(400), Decimal(250))
|
||||||
|
input_.product = tower
|
||||||
|
input_.quantity = 1
|
||||||
|
|
||||||
|
input_ = bom.inputs.new()
|
||||||
|
input_.product = create_product('Keyboard', Decimal(30), Decimal(10))
|
||||||
|
input_.quantity = 1
|
||||||
|
|
||||||
|
input_ = bom.inputs.new()
|
||||||
|
input_.product = create_product('Mouse', Decimal(10), Decimal(5))
|
||||||
|
input_.quantity = 1
|
||||||
|
|
||||||
|
input_ = bom.inputs.new()
|
||||||
|
input_.product = create_product('Screen', Decimal(300), Decimal(200))
|
||||||
|
input_.quantity = 1
|
||||||
|
|
||||||
|
output = bom.outputs.new()
|
||||||
|
computer = create_product('Computer', Decimal(750), Decimal(465))
|
||||||
|
computer.template.producible = True
|
||||||
|
computer.template.save()
|
||||||
|
output.product = computer
|
||||||
|
output.quantity = 1
|
||||||
|
|
||||||
|
bom.save()
|
||||||
|
computer.boms.new(bom=bom)
|
||||||
|
computer.save()
|
||||||
|
|
||||||
|
if 'production_routing' in activated:
|
||||||
|
setup_routing(config, activated, company)
|
||||||
|
|
||||||
|
if 'production_work' in activated:
|
||||||
|
WorkCenter = Model.get('production.work.center')
|
||||||
|
WorkCycle = Model.get('production.work.cycle')
|
||||||
|
setup_production_work(config, activated, company)
|
||||||
|
work_centers = WorkCenter.find([('parent', '=', None)])
|
||||||
|
|
||||||
|
today = dt.date.today()
|
||||||
|
production_date = today + relativedelta(months=-1)
|
||||||
|
while production_date <= today + relativedelta(days=20):
|
||||||
|
for _ in range(random.randint(0, 3)):
|
||||||
|
production = Production()
|
||||||
|
production.effective_date = production_date
|
||||||
|
production.product = computer
|
||||||
|
production.quantity = random.randint(1, 40)
|
||||||
|
production.bom = computer.boms[0].bom
|
||||||
|
|
||||||
|
if 'production_routing' in activated:
|
||||||
|
production.routing = computer.boms[0].routing
|
||||||
|
|
||||||
|
if 'production_work' in activated:
|
||||||
|
production.work_center = random.choice(work_centers)
|
||||||
|
|
||||||
|
production.save()
|
||||||
|
|
||||||
|
if (production_date < today) or (random.random() <= 1. / 3.):
|
||||||
|
production.click('wait')
|
||||||
|
if production_date < today:
|
||||||
|
production.click('assign_force')
|
||||||
|
production.click('run')
|
||||||
|
if random.random() <= 2. / 3.:
|
||||||
|
if 'production_work' in activated:
|
||||||
|
for work in production.works:
|
||||||
|
for _ in range(0, random.randint(1, 2)):
|
||||||
|
cycle = WorkCycle(
|
||||||
|
work=work,
|
||||||
|
duration=dt.timedelta(
|
||||||
|
seconds=random.randint(60, 3600)),
|
||||||
|
)
|
||||||
|
cycle.save()
|
||||||
|
cycle.click('run')
|
||||||
|
cycle.click('do')
|
||||||
|
output, = production.outputs
|
||||||
|
output.unit_price = (production.cost
|
||||||
|
/ Decimal(production.quantity)
|
||||||
|
).quantize(Decimal('0.0001'))
|
||||||
|
production.click('do')
|
||||||
|
production_date += relativedelta(days=random.randint(1, 3))
|
||||||
|
|
||||||
|
|
||||||
|
def setup_routing(config, activated, company):
|
||||||
|
Routing = Model.get('production.routing')
|
||||||
|
Operation = Model.get('production.routing.operation')
|
||||||
|
Product = Model.get('product.product')
|
||||||
|
|
||||||
|
routing = Routing(name='Computer routing rev1')
|
||||||
|
|
||||||
|
operation1 = Operation(name='Assemble pieces')
|
||||||
|
operation1.save()
|
||||||
|
step1 = routing.steps.new()
|
||||||
|
step1.operation = operation1
|
||||||
|
|
||||||
|
operation2 = Operation(name='Install software')
|
||||||
|
operation2.save()
|
||||||
|
step2 = routing.steps.new()
|
||||||
|
step2.operation = operation2
|
||||||
|
|
||||||
|
operation3 = Operation(name='Test')
|
||||||
|
operation3.save()
|
||||||
|
step3 = routing.steps.new()
|
||||||
|
step3.operation = operation3
|
||||||
|
|
||||||
|
operation4 = Operation(name='Package')
|
||||||
|
operation4.save()
|
||||||
|
step4 = routing.steps.new()
|
||||||
|
step4.operation = operation4
|
||||||
|
|
||||||
|
routing.boms.extend(routing.boms.find([('name', '=', 'Computer rev1')]))
|
||||||
|
|
||||||
|
routing.save()
|
||||||
|
|
||||||
|
computer, = Product.find([('name', '=', 'Computer')])
|
||||||
|
bom, = computer.boms
|
||||||
|
bom.routing = routing
|
||||||
|
bom.save()
|
||||||
|
|
||||||
|
|
||||||
|
def setup_production_work(config, activated, company):
|
||||||
|
WorkCenterCategory = Model.get('production.work.center.category')
|
||||||
|
WorkCenter = Model.get('production.work.center')
|
||||||
|
Operation = Model.get('production.routing.operation')
|
||||||
|
|
||||||
|
assembly = WorkCenterCategory(name='Assembly')
|
||||||
|
assembly.save()
|
||||||
|
operation, = Operation.find([('name', '=', 'Assemble pieces')])
|
||||||
|
operation.work_center_category = assembly
|
||||||
|
operation.save()
|
||||||
|
|
||||||
|
installation = WorkCenterCategory(name='Installation')
|
||||||
|
installation.save()
|
||||||
|
operations = Operation.find([
|
||||||
|
('name', 'in', ['Install software', 'Test']),
|
||||||
|
])
|
||||||
|
for operation in operations:
|
||||||
|
operation.work_center_category = installation
|
||||||
|
Operation.save(operations)
|
||||||
|
|
||||||
|
packaging = WorkCenterCategory(name='Packaging')
|
||||||
|
packaging.save()
|
||||||
|
operation, = Operation.find([('name', '=', 'Package')])
|
||||||
|
operation.work_center_category = packaging
|
||||||
|
operation.save()
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for i in range(1, 4):
|
||||||
|
line = WorkCenter(name='Line %i' % i)
|
||||||
|
|
||||||
|
assembly_line = line.children.new()
|
||||||
|
assembly_line.name = 'Assembly Line %i' % i
|
||||||
|
assembly_line.category = assembly
|
||||||
|
assembly_line.cost_method = 'cycle'
|
||||||
|
assembly_line.cost_price = Decimal(20)
|
||||||
|
|
||||||
|
installation_line = line.children.new()
|
||||||
|
installation_line.name = 'Installation Line %i' % i
|
||||||
|
installation_line.category = installation
|
||||||
|
installation_line.cost_method = 'hour'
|
||||||
|
installation_line.cost_price = Decimal(15)
|
||||||
|
|
||||||
|
packaging_line = line.children.new()
|
||||||
|
packaging_line.name = 'Packaging Line %i' % i
|
||||||
|
packaging_line.category = packaging
|
||||||
|
packaging_line.cost_method = 'hour'
|
||||||
|
packaging_line.cost_price = Decimal(10)
|
||||||
|
|
||||||
|
lines.append(line)
|
||||||
|
WorkCenter.save(lines)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import random
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, activated, company, customers):
|
||||||
|
Work = Model.get('project.work')
|
||||||
|
|
||||||
|
customer_projects = {
|
||||||
|
'Website': ['analysis', 'design', 'setup'],
|
||||||
|
'Labels': ['design'],
|
||||||
|
'Calendar': ['design'],
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, task_names in customer_projects.items():
|
||||||
|
project = Work(name=name, type='project', timesheet_available=False)
|
||||||
|
project.party = random.choice(customers)
|
||||||
|
for task_name in task_names:
|
||||||
|
task = Work(name=task_name, type='task', timesheet_available=True)
|
||||||
|
task.effort_duration = dt.timedelta(
|
||||||
|
days=random.randint(10, 30),
|
||||||
|
hours=random.randint(1, 5))
|
||||||
|
task.progress = random.randint(1, 100) // 5 * 5 / 100.
|
||||||
|
project.children.append(task)
|
||||||
|
project.save()
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import random
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company, suppliers):
|
||||||
|
Purchase = Model.get('purchase.purchase')
|
||||||
|
Product = Model.get('product.product')
|
||||||
|
|
||||||
|
all_products = Product.find([
|
||||||
|
('purchasable', '=', True),
|
||||||
|
])
|
||||||
|
today = dt.date.today()
|
||||||
|
purchase_date = today - relativedelta(days=60)
|
||||||
|
while purchase_date <= today + relativedelta(days=20):
|
||||||
|
supplier = random.choice(suppliers)
|
||||||
|
purchase = Purchase()
|
||||||
|
purchase.party = supplier
|
||||||
|
purchase.purchase_date = purchase_date
|
||||||
|
products = random.sample(
|
||||||
|
all_products, random.randint(1, len(all_products)))
|
||||||
|
for product in products:
|
||||||
|
purchase_line = purchase.lines.new()
|
||||||
|
purchase_line.product = product
|
||||||
|
purchase_line.quantity = random.randint(20, 100)
|
||||||
|
purchase_line.unit_price = product.cost_price
|
||||||
|
purchase.save()
|
||||||
|
threshold = 2. / 3.
|
||||||
|
if random.random() <= threshold:
|
||||||
|
purchase.click('quote')
|
||||||
|
if random.random() <= threshold:
|
||||||
|
purchase.click('confirm')
|
||||||
|
purchase.click('process')
|
||||||
|
elif random.choice([True, False]):
|
||||||
|
purchase.click('cancel')
|
||||||
|
purchase_date += relativedelta(days=random.randint(5, 10))
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import random
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, modules, company, customers):
|
||||||
|
Sale = Model.get('sale.sale')
|
||||||
|
Product = Model.get('product.product')
|
||||||
|
|
||||||
|
all_products = Product.find([
|
||||||
|
('salable', '=', True),
|
||||||
|
])
|
||||||
|
today = dt.date.today()
|
||||||
|
sale_date = today + relativedelta(months=-2)
|
||||||
|
while sale_date <= today + relativedelta(days=10):
|
||||||
|
for _ in range(random.randint(1, 5)):
|
||||||
|
customer = random.choice(customers)
|
||||||
|
sale = Sale()
|
||||||
|
sale.party = customer
|
||||||
|
sale.sale_date = sale_date
|
||||||
|
products = random.sample(
|
||||||
|
all_products, random.randint(1, len(all_products)))
|
||||||
|
for product in products:
|
||||||
|
sale_line = sale.lines.new()
|
||||||
|
sale_line.product = product
|
||||||
|
sale_line.quantity = random.randint(1, 50)
|
||||||
|
sale.save()
|
||||||
|
if sale_date <= today:
|
||||||
|
threshold = 2. / 3.
|
||||||
|
else:
|
||||||
|
threshold = 1. / 3.
|
||||||
|
if random.random() <= threshold:
|
||||||
|
sale.click('quote')
|
||||||
|
if random.random() <= threshold:
|
||||||
|
sale.click('confirm')
|
||||||
|
if random.random() <= threshold:
|
||||||
|
sale.click('process')
|
||||||
|
elif random.random() >= threshold:
|
||||||
|
sale.click('cancel')
|
||||||
|
elif random.random() >= threshold:
|
||||||
|
sale.click('cancel')
|
||||||
|
sale_date += relativedelta(days=random.randint(1, 3))
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, activated, company, suppliers):
|
||||||
|
ShipmentIn = Model.get('stock.shipment.in')
|
||||||
|
ShipmentOut = Model.get('stock.shipment.out')
|
||||||
|
|
||||||
|
for supplier in suppliers:
|
||||||
|
shipment = ShipmentIn()
|
||||||
|
shipment.supplier = supplier
|
||||||
|
all_moves = shipment.incoming_moves.find()
|
||||||
|
moves = random.sample(all_moves, len(all_moves) * 2 // 3)
|
||||||
|
while moves:
|
||||||
|
shipment = ShipmentIn()
|
||||||
|
shipment.supplier = supplier
|
||||||
|
for _ in range(random.randint(1, len(moves))):
|
||||||
|
move = moves.pop()
|
||||||
|
shipment.incoming_moves.append(move)
|
||||||
|
shipment.click('receive')
|
||||||
|
shipment.click('do')
|
||||||
|
|
||||||
|
shipments = ShipmentOut.find([('state', '=', 'waiting')])
|
||||||
|
for shipment in shipments:
|
||||||
|
if shipment.click('assign_try'):
|
||||||
|
shipment.click('pick')
|
||||||
|
shipment.click('pack')
|
||||||
|
shipment.click('do')
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime as dt
|
||||||
|
import random
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def setup(config, activated, company):
|
||||||
|
Work = Model.get('timesheet.work')
|
||||||
|
Employee = Model.get('company.employee')
|
||||||
|
Line = Model.get('timesheet.line')
|
||||||
|
|
||||||
|
for name in ['Marketing', 'Accounting', 'Secretary']:
|
||||||
|
work = Work(name=name)
|
||||||
|
work.save()
|
||||||
|
|
||||||
|
employees = Employee.find([('company', '=', company.id)])
|
||||||
|
works = Work.find([])
|
||||||
|
|
||||||
|
today = dt.date.today()
|
||||||
|
date = today + relativedelta(months=-1)
|
||||||
|
day = dt.timedelta(hours=8)
|
||||||
|
while date <= today:
|
||||||
|
if date.weekday() < 5:
|
||||||
|
for employee in employees:
|
||||||
|
total = dt.timedelta()
|
||||||
|
while total < day:
|
||||||
|
if random.random() > 0.8:
|
||||||
|
break
|
||||||
|
line = Line(employee=employee, date=date)
|
||||||
|
line.work = random.choice(works)
|
||||||
|
duration = dt.timedelta(hours=random.randint(1, 8))
|
||||||
|
line.duration = min(duration, day - total)
|
||||||
|
line.save()
|
||||||
|
date += dt.timedelta(days=1)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
from proteus import Model
|
||||||
|
|
||||||
|
|
||||||
|
def format_warning(name, records):
|
||||||
|
key = '|'.join(map(str, records)).encode('utf-8')
|
||||||
|
return '%s.%s' % (hashlib.md5(key).hexdigest(), name)
|
||||||
|
|
||||||
|
|
||||||
|
def skip_warning(config, name, records):
|
||||||
|
Warning_ = Model.get('res.user.warning')
|
||||||
|
Warning_(user=config.user, name=format_warning(name, records)).save()
|
||||||