reconfigure get_tasks and get_command to print

This commit is contained in:
Wilson Gomez 2023-10-20 16:56:19 -05:00
parent 8d36b1511a
commit 6b437d7e6b
13 changed files with 351 additions and 81 deletions

View File

@ -27,9 +27,10 @@ def register():
sale.OrderStatusTime,
shop.SaleShop,
bom.BOM,
production.WorkStation,
production.WorkStationPrinter,
# production.WorkStation,
# production.WorkStationPrinter,
production.ConfigurationTask,
production.TaskPrinter,
production.Task,
product.ProductMixOption,
product.Product,

3
bom.py
View File

@ -12,8 +12,6 @@ def round_dec(number):
class BOM(metaclass=PoolMeta):
__name__ = 'production.bom'
tasks_configuration = fields.One2Many('production.configuration_task', 'ldm', 'Tasks Configuration')
@classmethod
def copy(cls, records, default=None):
if default is None:
@ -21,5 +19,4 @@ class BOM(metaclass=PoolMeta):
else:
default = default.copy()
default.setdefault('output_products', None)
default.setdefault('tasks_configuration', None)
return super(BOM, cls).copy(records, default=default)

View File

@ -5,6 +5,7 @@ from trytond.pool import PoolMeta
from .exceptions import ProductMixRequiredError
from trytond.i18n import gettext
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
products_mix = fields.Many2Many('product.product-mix.option',
@ -17,8 +18,8 @@ class Product(metaclass=PoolMeta):
if self.products_mix and self.quantity_mix_required and len(self.products_mix) < self.quantity_mix_required:
raise ProductMixRequiredError(
gettext(
"sale_pos_frontend_rest.msg_quantity_mix_error",
product_mix=len(self.products_mix),
"sale_pos_frontend_rest.msg_quantity_mix_error",
product_mix=len(self.products_mix),
quantity=self.quantity_mix_required))
@classmethod

View File

@ -4,10 +4,11 @@
from trytond.model import fields, ModelSQL, ModelView
from trytond.transaction import Transaction
from decimal import Decimal
from trytond.pool import PoolMeta, Pool
from datetime import datetime, timedelta
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.exceptions import UserError
from trytond.i18n import gettext
# from trytond.exceptions import UserError
# from trytond.i18n import gettext
def round_dec(number):
@ -16,21 +17,29 @@ def round_dec(number):
STATES = {'required': True}
# for remove
# class WorkStation(ModelSQL, ModelView):
# "Work Station"
# __name__ = 'production.workstation'
class WorkStation(ModelSQL, ModelView):
"Work Station"
__name__ = 'production.workstation'
# name = fields.Char('Name', states=STATES)
# code = fields.Char('Code', states=STATES)
# printers = fields.Many2Many('production.workstation.pos_printer', 'work_station', 'printer', 'Printers')
name = fields.Char('Name', states=STATES)
code = fields.Char('Code', states=STATES)
printers = fields.Many2Many('production.workstation.pos_printer', 'work_station', 'printer', 'Printers')
# for remove
# class WorkStationPrinter(ModelSQL, ModelView):
# "Work Station"
# __name__ = 'production.workstation.pos_printer'
# work_station = fields.Many2One('production.workstation', 'Work Station')
# printer = fields.Many2One('sale.pos_printer', 'Printer')
class WorkStationPrinter(ModelSQL, ModelView):
"Work Station"
__name__ = 'production.workstation.pos_printer'
class TaskPrinter(ModelSQL, ModelView):
"Task Printer"
__name__ = 'production.task.pos_printer'
work_station = fields.Many2One('production.workstation', 'Work Station')
task = fields.Many2One('production.configuration_task', 'Tasks')
printer = fields.Many2One('sale.pos_printer', 'Printer')
@ -40,24 +49,33 @@ class ConfigurationTask(ModelSQL, ModelView):
name = fields.Char('Name', states=STATES)
description = fields.Text('Description')
ldm = fields.Many2One('production.bom', 'LDM', states=STATES)
product = fields.Many2One('product.product', 'Product',
search_context={
'outputs': Eval('_parent_ldm', {}).get('outputs')})
work_station = fields.Many2One('production.workstation', 'Work Station', states=STATES)
printers = fields.Many2Many('production.task.pos_printer', 'task',
'printer', 'Printers', states=STATES)
# for remove
# ldm = fields.Many2One('production.bom', 'LDM', states=STATES)
# work_station = fields.Many2One('production.workstation', 'Work Station', states=STATES)
@classmethod
def create(cls, vlist):
pool = Pool()
LDM = pool.get('production.bom')
vlist = [x.copy() for x in vlist]
for vals in vlist:
if 'ldm' in vals:
ldm = LDM(vals['ldm'])
if not ldm.outputs:
raise UserError(gettext('sale_pos_frontend_rest.msg_missing_product_output'))
vals['product'] = ldm.outputs[0].product.id
return super(ConfigurationTask, cls).create(vlist)
def __register__(cls, module_name):
super(ConfigurationTask, cls).__register__(module_name)
table = cls.__table_handler__(module_name)
if table.column_exist('ldm'):
TaskPrinter = Pool().get('production.task.pos_printer')
query = '''select t.id, p.printer from
production_configuration_task as t
join production_workstation_pos_printer as p
on p.work_station=t.work_station'''
cursor = Transaction().connection.cursor()
cursor.execute(query)
res = cursor.fetchall()
to_create = [{'task': t, 'printer': p} for t, p in res]
TaskPrinter.create(to_create)
table.drop_column('ldm')
table.drop_column('work_station')
class Task(ModelSQL, ModelView):
@ -65,17 +83,63 @@ class Task(ModelSQL, ModelView):
__name__ = 'production.task'
name = fields.Char('Name', states=STATES)
description = fields.Text('Description')
ldm = fields.Many2One('production.bom', 'LDM', states=STATES)
work_station = fields.Many2One('production.workstation', 'Work Station', states=STATES)
planned_date = fields.Date('Planned Date')
note = fields.Text('Note')
line = fields.Many2One('sale.line', 'Sale Line', states={'readonly': True})
quantity = fields.Integer('Quantity')
state = fields.Selection([('pending', 'Pending'), ('done', 'Done')], 'State')
state = fields.Selection([
('pending', 'Pending'),
('commanded', 'Commanded'),
('done', 'Done')], 'State')
printer = fields.Many2One('sale.pos_printer', 'Printer')
task = fields.Many2One('production.configuration_task', 'Task')
sale_number = fields.Char('Sale Number')
# ldm = fields.Many2One('production.bom', 'LDM', states=STATES)
@classmethod
def __setup__(cls):
super(Task, cls).__setup__()
@classmethod
def get_tasks_to_print(cls, args):
one_hour_ago = str(datetime.now() - timedelta(hours=1))
dom = [
('state', '=', 'pending'),
('create_date', '>=', one_hour_ago)
]
if args.get('sale_id'):
dom.append('line.sale', '=', args['sale_id'])
fields = [
'name', 'note', 'quantity', 'sale_number',
'line', 'line.sale',
'printer.name', 'printer.shop', 'printer.host',
'printer.interface', 'printer.port', 'printer.row_characters',
]
tasks = cls.search_read(dom, fields_names=fields, order=[('id', 'DESC')])
tasks_print = {}
for t in tasks:
printer_id = t['printer.']['id']
sale_id = t['line.']['sale']
key = str(printer_id) + '_' + str(sale_id)
line = {
'quantity': t['quantity'],
'name': t['name'],
'line': t['line.']['id'],
'task': t['id'],
'note': t['note']
}
try:
tasks_print[key]['lines'].append(line)
except Exception:
tasks_print[key] = {}
tasks_print[key]['lines'] = [line]
value_printer = t['printer.']
value_printer['device'] = value_printer['host']
value_printer['profile'] = ''
tasks_print[key]['printer'] = t['printer.']
tasks_print[key]['sale'] = t['sale_number']
tasks_print[key]['work_station'] = value_printer['name']
return list(tasks_print.values())
# class Production(metaclass=PoolMeta):
# __name__ = 'production'

258
sale.py
View File

@ -88,16 +88,24 @@ class Sale(metaclass=PoolMeta):
"""
Status = Pool().get('sale.order_status.time')
Line = Pool().get('sale.line')
sale = cls(args['sale_id'])
to_write = {'order_status': 'commanded'}
now = datetime.now()
order_time = sale.order_status_time
if order_time:
Status.write([order_time], {'commanded': now})
lines_ = args.get('lines_ids', [])
if args.get('sale_id'):
sale = cls(args['sale_id'])
sales = [sale]
else:
status, = Status.create([{'commanded': now, 'requested': now, 'sale': args['sale_id']}])
to_write['order_status_time'] = status
cls.write([sale], to_write)
lines = Line.browse(lines_)
sales = set(ln.sale for ln in lines)
for sale in sales:
to_write = {'order_status': 'commanded'}
now = datetime.now()
order_time = sale.order_status_time
if order_time:
Status.write([order_time], {'commanded': now})
else:
status, = Status.create([{'commanded': now, 'requested': now, 'sale': sale.id}])
to_write['order_status_time'] = status
cls.write([sale], to_write)
if args.get('lines_ids'):
lines_ids = args['lines_ids']
lines = Line.browse(lines_ids)
@ -113,22 +121,20 @@ class Sale(metaclass=PoolMeta):
@classmethod
def get_orders_to_command(cls, args):
# function deprecated for remove
pool = Pool()
Line = pool.get('sale.line')
WorkStation = pool.get('production.workstation')
shop = args['shop']
stations = WorkStation.search_read([],
fields_names=[
"name", "printers.shop",
"printers.host", "printers.interface",
"printers.port", "printers.row_characters"])
stations = {s['id']: s for s in stations}
_date = str(datetime.now() - timedelta(hours=1))
fields = [
'sale.number', 'quantity', 'note',
'product.tasks.work_station',
'product.tasks.printers.shop',
'product.tasks.printers.name',
'product.tasks.printers.host',
'product.tasks.printers.interface',
'product.tasks.printers.port',
'product.tasks.printers.row_characters',
'product.tasks.name']
dom = [
("sale.shop", "=", shop),
@ -149,6 +155,7 @@ class Sale(metaclass=PoolMeta):
sale_number = line['sale.']['number']
qty = line['quantity']
note = line['note']
id_ = str(line['id'])
try:
data[sale_id]
@ -160,13 +167,17 @@ class Sale(metaclass=PoolMeta):
}
for t in line['product.']['tasks.']:
line_ = {'qty': qty, 'note': note, 'name': t['name']}
station_id = t['work_station']
station = stations[station_id]
for p in station['printers.']:
key = str(p['id']) + '_' + str(station_id)
line_ = {
'quantity': qty, 'note': note,
'name': t['name'], 'line': id_,
'task': str(t['id'])}
for p in t['printers.']:
key = str(p['id'])
if p['shop'] == shop:
value = {
**line_,
'printer': p['id']
}
try:
data[sale_id]['tasks'][key]['lines'].append(line_)
except Exception:
@ -175,7 +186,7 @@ class Sale(metaclass=PoolMeta):
data[sale_id]['tasks'][key] = {
'printer': p,
'sale': sale_number,
'work_station': station['name'],
'work_station': p['name'],
'lines': [line_]
}
@ -190,10 +201,7 @@ class Sale(metaclass=PoolMeta):
return list(data.values())
def get_data_for_stations(self):
# TaskConfig = Pool().get('production.configuration_task')
# Line = Pool().get('sale.line')
# print('ingesa nnn', self.id)
# print(line.status_order, 'status order')
# function deprecated
data_grouped_printer = {}
if not self.number:
self.set_number([self])
@ -201,10 +209,11 @@ class Sale(metaclass=PoolMeta):
shop = self.shop
line_commanded = []
for line in self.lines:
if line.status_order in ('draft', 'requested'):
if not line.task_printed:
line_commanded.append(line)
qty = line.quantity
note = line.note
line_id = line.id
tasks = line.product.tasks
att_getter = attrgetter("name")
att_getter_p = attrgetter("host", "interface", "port", "row_characters")
@ -212,7 +221,9 @@ class Sale(metaclass=PoolMeta):
station = t.work_station
station_id = station.id
name = att_getter(t)
value = {'name': name, 'qty': qty, 'note': note}
value = {
'name': name, 'qty': qty, 'note': note,
'id': line_id, 'task_id': t.id}
for p in t.work_station.printers:
key = str(p.id) + '_' + str(station_id)
if p.shop == shop:
@ -488,11 +499,196 @@ class SaleLine(metaclass=PoolMeta):
__name__ = 'sale.line'
production = fields.Many2One('production', 'Production')
status_order = fields.Selection(OPTIONS_STATUS, 'Status Order')
without_task = fields.Boolean('Without Task')
tasks = fields.One2Many('production.task', 'line', 'Tasks')
@staticmethod
def default_status_order():
return 'draft'
@classmethod
def mark_tasks_printed(cls, args):
Task = Pool().get('production.task')
task_ids = args.get('task_ids')
tasks = Task.browse(task_ids)
Task.write(list(tasks), {'state': 'commanded'})
@classmethod
def get_data_command_and_task(cls, args):
orders = cls.get_data_command(args)
tasks = cls.get_data_tasks(args)
return {'orders': orders, 'tasks': tasks}
@classmethod
def get_data_command(cls, args):
Sale = Pool().get('sale.sale')
Printer = Pool().get('sale.pos_printer')
one_hour_ago = str(datetime.now() - timedelta(hours=1))
shop = args.get('shop')
fields_printer = [
'shop', 'name',
'host', 'interface',
'port', 'row_characters',
]
printers = Printer.search_read(['shop', '=', shop],
fields_names=fields_printer)
printers = {p['id']: p for p in printers}
dom = [
("sale.shop", "=", shop),
("sale.state", "in", ("draft", "quotation")),
("status_order", "=", 'requested'),
("create_date", ">=", one_hour_ago),
]
if args.get('sale_id'):
dom.append(('sale', '=', args['sale_id']))
fields = [
'sale', 'product.name',
'product.template.printers',
'product.template.categories',
'quantity', 'note'
]
lines = cls.search_read(dom, fields_names=fields)
sale_ids = set(ln['sale'] for ln in lines)
fields_sales = [
'consumer.name', 'consumer.phone',
'consumer.address', 'consumer.notes',
'party.name', 'turn', 'number', 'invoice_number',
'position', 'salesman.rec_name', 'comment',
'delivery_charge', 'payment_term.name', 'delivery_amount',
'total_amount', 'shop.name', 'kind', 'table_assigned.name'
]
sales = Sale.search_read(['id', 'in', sale_ids], fields_names=fields_sales)
sales = {
s['id']: {
'id': s['id'],
'consumer': s['consumer.'],
'turn': s['turn'],
'number': s['invoice_number'],
'sale_number': s['number'],
'position': s.get('position', ''),
'party': s.get('party.', {}).get('name'),
'kind': s['kind'],
'delivery_amount': s['delivery_amount'],
'salesman': s.get('salesman.', {}).get('rec_name'),
'comment': s.get('comment', ''),
'payment_term': s.get('payment_term.', {}).get('name', ''),
'delivery_charge': s['delivery_charge'],
'total_amount': str(s['total_amount']),
'shop': s.get('shop.', {}).get('name', ''),
'table_assigned': s.get('table_assigned.', {}).get('name', ''),
}
for s in sales
}
orders = {}
lines_mark_sended = []
for line in lines:
sale_id = line['sale']
sale = sales[sale_id]
printers_ = line['product.']['template.'].get('printers', [])
if not printers_:
lines_mark_sended.append(line['id'])
continue
value_line = {
'name': line['product.']['name'],
'quantity': str(line['quantity']),
'unit_price': int(0), # validate is this field is neccesary
'note': line['note'],
'id': line['id']
}
categories = line['product.']['template.'].get('categories')
for printer_id in printers_:
printer = printers.get(printer_id)
if not printer:
continue
key = f'{sale_id}_{printer_id}'
if key not in orders:
orders[key] = {**printer, **sale, 'lines': []}
if 'categories.' in printer:
orders[key]['lines'] = {
c['sequence']: {
'name': c.get('category.', {}).get('name'),
'lines': []} for c in printer['categories']}
orders[key]['categories'] = {c['category.']['id']: c['sequence'] for c in printer['categories.']}
if isinstance(orders[key]['lines'], list):
orders[key]['lines'].append(value_line)
else:
key_id = orders[key]['categories'].get(categories[0], 'others')
if 'others' not in orders[key]['lines']:
orders[key]['lines']['others'] = {'name': 'OTROS', 'lines': []}
orders[key]['lines'][key_id]['lines'].append(value_line)
return list(orders.values())
@classmethod
def get_data_tasks(cls, args):
Task = Pool().get('production.task')
one_hour_ago = str(datetime.now() - timedelta(hours=1))
shop = args['shop']
fields = [
'sale.number', 'quantity', 'note',
'product.tasks.printers.shop',
'product.tasks.printers.name',
'product.tasks.printers.host',
'product.tasks.printers.interface',
'product.tasks.printers.port',
'product.tasks.printers.row_characters',
'product.tasks.name']
dom = [
("sale.shop", "=", shop),
("sale.state", "in", ("draft", "quotation")),
("create_date", ">=", one_hour_ago),
("without_task", "!=", True),
("tasks", '=', None)
]
if args.get('sale_id'):
dom.append(('sale', '=', args['sale']))
lines = cls.search_read(
dom, fields_names=fields,
order=[('sale', 'ASC'), ('id', 'DESC')])
to_create = []
lines_without_tasks = []
print(lines, 'validate tasks')
for line in lines:
quantity = line['quantity']
note = line['note']
line_id = line['id']
sale_number = line['sale.']['number']
tasks = line['product.']['tasks.']
if not tasks:
lines_without_tasks.append(line_id)
for t in line['product.']['tasks.']:
task_id = t['id']
for p in t['printers.']:
if p['shop'] == shop:
value = {
'quantity': quantity,
'note': note,
'line': line_id,
'name': t['name'],
'sale_number': sale_number,
'task': task_id,
'state': 'pending',
'printer': p['id']}
to_create.append(value)
if lines_without_tasks:
lines_ = cls.browse(lines_without_tasks)
cls.write(list(lines_), {'without_task': True})
Task.create(to_create)
data = Task.get_tasks_to_print(args)
return data
@classmethod
def delete(cls, lines):
HistoryDelete = Pool().get('sale.line._history.delete')

View File

@ -1,5 +1,5 @@
[tryton]
version=6.0.6
version=6.0.7
depends:
sale
production_accounting

View File

@ -3,9 +3,9 @@
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook/page[@id='lines']" position="after">
<page string="Tasks Configuration" id="tasks">
<!-- <page string="Tasks Configuration" id="tasks">
<field name="tasks_configuration" colspan="4"
view_ids="sale_pos_frontend_rest.configuration_task_tree,sale_pos_frontend_rest.configuration_task_form"/>
</page>
</page> -->
</xpath>
</data>

View File

@ -4,13 +4,15 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<form>
<label name="name"/>
<field name="name"/>
<label name="ldm"/>
<field name="ldm"/>
<!-- <label name="ldm"/>
<field name="ldm"/> -->
<label name="product"/>
<field name="product"/>
<label name="work_station"/>
<field name="work_station"/>
<!-- <label name="work_station"/>
<field name="work_station"/> -->
<newline/>
<label name="description"/>
<field name="description" colspan="4"/>
<!-- <label name="printers"/> -->
<field name="printers" colspan="4"/>
</form>

View File

@ -3,7 +3,7 @@
The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
<tree>
<field name="name"/>
<field name="ldm"/>
<field name="work_station"/>
<!-- <field name="ldm"/> -->
<!-- <field name="work_station"/> -->
<field name="product"/>
</tree>

View File

@ -8,4 +8,8 @@ this repository contains the full copyright notices and license terms. -->
<label name="quantity_mix_required" />
<field name="quantity_mix_required" />
</xpath>
<xpath expr="/form/notebook/page[@id='printers']/field[@name='printers']"
position="after">
<field name="tasks" colspan="4"/>
</xpath>
</data>

View File

@ -6,12 +6,14 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<field name="name"/>
<label name="ldm"/>
<field name="ldm"/>
<label name="work_station"/>
<field name="work_station"/>
<!-- <label name="work_station"/>
<field name="work_station"/> -->
<label name="quantity"/>
<field name="quantity"/>
<label name="planned_date"/>
<field name="planned_date"/>
<label name="printer"/>
<field name="printer"/>
<newline/>
<label name="description"/>
<field name="description" colspan="4"/>

View File

@ -4,7 +4,7 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<tree>
<field name="name"/>
<field name="ldm"/>
<field name="work_station"/>
<!-- <field name="work_station"/> -->
<field name="planned_date"/>
<field name="quantity"/>
<field name="state"/>

View File

@ -8,6 +8,9 @@ copyright notices and license terms. -->
<page string="Production" id="production">
<label name="production"/>
<field name="production"/>
<label name="without_task"/>
<field name="without_task"/>
<!-- <field name="tasks" colspan="4"/> -->
</page>
</xpath>
</data>