diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2023-01-13 04:41:16 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2023-01-13 04:41:16 +0000 |
| commit | 45b8c4757ba6107037c3e1f1e2a64c9e47e8ae48 (patch) | |
| tree | 7d088c21df7a7ac74d896259aefa94d940920294 | |
| parent | 0f8fbe56e89ec285c6fbcdd2bed5a67f62bcfe59 (diff) | |
| parent | 6fe453ed5da6cfda56f4af454dbedc00b97f0f9e (diff) | |
Merged in staging (pull request #19)
Staging
| -rw-r--r-- | indoteknik_api/controllers/api_v1/__init__.py | 1 | ||||
| -rw-r--r-- | indoteknik_api/controllers/api_v1/partner.py | 37 | ||||
| -rw-r--r-- | indoteknik_api/controllers/api_v1/product.py | 25 | ||||
| -rw-r--r-- | indoteknik_api/controllers/api_v1/sale_order.py | 6 | ||||
| -rw-r--r-- | indoteknik_api/controllers/api_v1/user.py | 13 | ||||
| -rw-r--r-- | indoteknik_api/controllers/controller.py | 68 | ||||
| -rw-r--r-- | indoteknik_api/models/res_users.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/__manifest__.py | 2 | ||||
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 65 | ||||
| -rw-r--r-- | indoteknik_custom/models/dunning_run.py | 53 | ||||
| -rwxr-xr-x | indoteknik_custom/models/product_template.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/res_partner.py | 7 | ||||
| -rwxr-xr-x | indoteknik_custom/models/x_manufactures.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/report/report_invoice.xml | 4 | ||||
| -rw-r--r-- | indoteknik_custom/views/dunning_run.xml | 6 | ||||
| -rw-r--r-- | indoteknik_custom/views/ir_sequence.xml | 10 | ||||
| -rw-r--r-- | indoteknik_custom/views/res_partner.xml | 15 | ||||
| -rwxr-xr-x | indoteknik_custom/views/x_manufactures.xml | 16 |
18 files changed, 256 insertions, 77 deletions
diff --git a/indoteknik_api/controllers/api_v1/__init__.py b/indoteknik_api/controllers/api_v1/__init__.py index 03737d9d..e09b8f7b 100644 --- a/indoteknik_api/controllers/api_v1/__init__.py +++ b/indoteknik_api/controllers/api_v1/__init__.py @@ -6,6 +6,7 @@ from . import city from . import district from . import flash_sale from . import manufacture +from . import partner from . import product_variant from . import product from . import promotion diff --git a/indoteknik_api/controllers/api_v1/partner.py b/indoteknik_api/controllers/api_v1/partner.py new file mode 100644 index 00000000..043a82b8 --- /dev/null +++ b/indoteknik_api/controllers/api_v1/partner.py @@ -0,0 +1,37 @@ +from .. import controller +from odoo import http +from odoo.http import request + + +class Partner(controller.Controller): + prefix = '/api/v1/' + + @http.route(prefix + 'partner', auth='public', methods=['POST', 'OPTIONS'], csrf=False) + def create_partner(self, **kw): + if not self.authenticate(): + return self.response(code=401, description='Unauthorized') + + validate_request = self.get_request_params(kw, { + 'user_id': ['required', 'number'], + 'partner_id': ['required', 'number', 'alias:parent_id'], + 'type': ['default:other'], + 'name': ['required'], + 'email': ['required'], + 'mobile': ['required'], + 'street': ['required'], + 'city_id': ['required', 'number', 'alias:kota_id'], + 'district_id': ['number', 'alias:kecamatan_id'], + 'sub_district_id': ['number', 'alias:kelurahan_id'], + 'zip': ['required'], + }) + + if not validate_request['valid']: + return self.response(code=400, description=validate_request) + + del validate_request['value']['user_id'] + partner = request.env['res.partner'].create([ validate_request['value'] ]) + + return self.response({ + 'id': partner.id, + }) + diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py index 2e978679..28a63ed5 100644 --- a/indoteknik_api/controllers/api_v1/product.py +++ b/indoteknik_api/controllers/api_v1/product.py @@ -6,7 +6,30 @@ import ast class Product(controller.Controller): prefix = '/api/v1/' - + + @http.route(prefix + 'new_product', auth='public', methods=['GET', 'OPTIONS']) + def get_new_product(self): + if not self.authenticate(): + return self.response(code=401, description='Unauthorized') + base_url = request.env['ir.config_parameter'].get_param('web.base.url') + query = [('show_as_new_product', '=', True)] + brands = request.env['x_manufactures'].search(query, order='sequence') + data = [] + for brand in brands: + query_products = [ + ('is_new_product', '=', True), + ('x_manufacture', '=', brand.id), + ] + products = request.env['product.template'].search(query_products, order='name') + data.append({ + 'manufacture_id': brand.id, + 'sequence': brand.sequence, + 'name': brand.x_name, + 'image': base_url + 'api/image/x_manufactures/x_logo_manufacture/' + str(brand.id) if brand.x_logo_manufacture else '', + 'products': [request.env['product.template'].api_single_response(x) for x in products] + }) + return self.response(data) + @http.route(prefix + 'product', auth='public', methods=['GET', 'OPTIONS']) def get_product(self, **kw): if not self.authenticate(): diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 5604a86c..a8c5bacc 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -10,12 +10,6 @@ class SaleOrder(controller.Controller): def create_sale_order(self, **kw): if not self.authenticate(): return self.response(code=401, description='Unauthorized') - - user_id = kw.get('user_id') - - is_verify = self.verify_user_token(user_id) - if not is_verify: - return self.response(code=401, description='Unauthorized') product_pricelist_default_discount_id = request.env['ir.config_parameter'].get_param('product.pricelist.default_discount_id') product_pricelist_default_discount_id = int(product_pricelist_default_discount_id) diff --git a/indoteknik_api/controllers/api_v1/user.py b/indoteknik_api/controllers/api_v1/user.py index bf1814da..ae04e0ff 100644 --- a/indoteknik_api/controllers/api_v1/user.py +++ b/indoteknik_api/controllers/api_v1/user.py @@ -109,11 +109,7 @@ class User(controller.Controller): user = request.env['res.users'].search([('id', '=', id)], limit=1) if not user: - return self.response(code=400, description='User not found') - - is_verify = self.verify_user_token(id) - if not is_verify: - return self.response(code=401, description='Unauthorized') + return self.response(code=404, description='User not found') allowed_field = ['name', 'phone', 'mobile', 'password'] for field in allowed_field: @@ -136,11 +132,8 @@ class User(controller.Controller): if not user: return self.response(code=404, description='User not found') - is_verify = self.verify_user_token(id) - if not is_verify: - return self.response(code=401, description='Unauthorized') - - partners = [user.partner_id] + [x for x in user.child_ids] + partner_ids = [user.partner_id.id] + [x.id for x in user.child_ids] + partners = request.env['res.partner'].search([('id', 'in', partner_ids)], order='create_date DESC') address = [request.env['res.users'].api_address_response(x) for x in partners] return self.response(address) diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py index 73c8829d..a08d9fa4 100644 --- a/indoteknik_api/controllers/controller.py +++ b/indoteknik_api/controllers/controller.py @@ -30,23 +30,58 @@ class Controller(http.Controller): except: authorization = None token = request.env['ir.config_parameter'].sudo().get_param('rest_api_token') or '' + result = False if authorization == token: request.session.authenticate(config.get('db_name'), 'it@fixcomart.co.id', 'Fixcomart378') - return True - return False - - def validate_request(self, rules: dict, kw: dict): - validation = { - 'status': True, - 'reason': [] + result = True + if self.verify_user_token(): + result = True + return result + + def get_request_params(self, kw, queries): + result = { + 'valid': True, + 'reason': [], + 'value': {}, + 'query': {} } - for key in rules: - values = rules[key] - for value in values: - if value == 'required' and not kw.get(key): - validation['status'] = False - validation['reason'].append(key + ' is ' + value) - return validation + for key in queries: + rules = queries[key] + is_number = len([r for r in rules if r == 'number']) > 0 + + has_alias = [r for r in rules if r.startswith('alias:')] + alias = key + if len(has_alias) > 0: + alias = has_alias[0].replace('alias:', '') + + has_default = [r for r in rules if r.startswith('default:')] + default = None + if len(has_default) > 0: + default = has_default[0].replace('default:', '') + + value = kw.get(key, '') + if value in ['null', 'undefined']: + value = '' + for rule in rules: + if rule == 'required' and not value: + result['reason'].append(key + ' is ' + rule) + elif rule == 'number' and value and not value.isdigit(): + result['reason'].append(key + ' must be ' + rule) + + if not value and default: + value = default + if is_number and value.isdigit(): + value = int(value) + if not value: + value = None + result['value'][alias] = value + result['query'][key] = value + + if len(result['reason']) > 0: + result['valid'] = False + if not result['valid']: + del result['value'] + return result def time_to_str(self, object, format): time = '' @@ -83,11 +118,12 @@ class Controller(http.Controller): def create_user_token(self, user): return jwt.encode({'id': user.id}, self.jwt_secret_key) - def verify_user_token(self, user_id): + def verify_user_token(self): try: token = request.httprequest.environ['HTTP_TOKEN'] user_token = jwt.decode(token, self.jwt_secret_key, algorithms=['HS256']) - if int(user_id) != user_token['id']: + user = request.env['res.users'].search([('id', '=', user_token['id'])]) + if not user: return False return True except: diff --git a/indoteknik_api/models/res_users.py b/indoteknik_api/models/res_users.py index 8eddc85e..e5b4bed6 100644 --- a/indoteknik_api/models/res_users.py +++ b/indoteknik_api/models/res_users.py @@ -20,6 +20,7 @@ class ResUsers(models.Model): def api_address_response(self, user): data = { 'id': user.id, + 'type': user.type, 'name': user.name, 'mobile': user.mobile, 'street': user.street, diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 421b7cb2..908e74df 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -15,6 +15,7 @@ 'views/coupon_program.xml', 'views/delivery_order.xml', 'views/product_pricelist.xml', + 'views/res_partner.xml', 'views/product_pricelist_item.xml', 'views/product_public_category.xml', 'views/product_template.xml', @@ -60,6 +61,7 @@ 'report/report_banner_banner.xml', 'report/report_banner_banner2.xml', 'report/purchase_order.xml', + 'report/report_invoice.xml' ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 3d4d646b..8ada3b95 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -1,45 +1,46 @@ -from . import x_banner_banner -from . import x_banner_category -from . import x_biaya_kirim -from . import x_manufactures +from . import account_asset +from . import account_move +from . import blog_post from . import coupon_program +from . import crm_lead +from . import custom_mail_marketing +from . import customer_review +from . import delivery_carrier +from . import delivery_order +from . import dunning_run +from . import invoice_reklas +from . import ir_attachment +from . import mail_mail +from . import product_pricelist from . import product_public_category +from . import product_spec from . import product_template -from . import x_partner_purchase_order -from . import x_product_tags -from . import stock_vendor -from . import crm_lead -from . import res_users -from . import user_activity_log +from . import purchase_order_line from . import purchase_order +from . import purchase_outstanding from . import purchase_pricelist -from . import purchase_order_line -from . import sale_order +from . import res_partner +from . import res_users from . import sale_monitoring_detail from . import sale_monitoring -from . import account_move -from . import account_asset -from . import blog_post +from . import sale_order +from . import sales_outstanding +from . import sales_target from . import stock_move -from . import stock_picking +from . import stock_picking_return from . import stock_picking_type -from . import delivery_order -from . import product_pricelist +from . import stock_picking +from . import stock_vendor +from . import user_activity_log from . import users -from . import ir_attachment -from . import delivery_carrier -from . import dunning_run -from . import stock_picking_return -from . import website_user_cart -from . import website_user_wishlist from . import website_brand_homepage -from . import mail_mail from . import website_categories_homepage -from . import sales_target -from . import product_spec -from . import purchase_outstanding -from . import sales_outstanding -from . import customer_review from . import website_content -from . import invoice_reklas -from . import custom_mail_marketing +from . import website_user_cart +from . import website_user_wishlist +from . import x_banner_banner +from . import x_banner_category +from . import x_biaya_kirim +from . import x_manufactures +from . import x_partner_purchase_order +from . import x_product_tags diff --git a/indoteknik_custom/models/dunning_run.py b/indoteknik_custom/models/dunning_run.py index 5d98bb98..ed9aa7c0 100644 --- a/indoteknik_custom/models/dunning_run.py +++ b/indoteknik_custom/models/dunning_run.py @@ -10,24 +10,55 @@ class DunningRun(models.Model): _description = 'Dunning Run' _order = 'dunning_date desc, id desc' - number = fields.Char(string='Document No', index=True, required=True, copy=False, readonly=True) - dunning_date = fields.Date(string='Dunning Date') + number = fields.Char(string='Document No', index=True, copy=False, readonly=True) + dunning_date = fields.Date(string='Dunning Date', required=True) partner_id = fields.Many2one( 'res.partner', string='Customer', required=True, change_default=True, index=True, tracking=1) dunning_line = fields.One2many('dunning.run.line', 'dunning_id', string='Dunning Lines', auto_join=True) - dunning_level = fields.Integer(string='Dunning Level', default=30, help='30 hari sebelum jatuh tempo invoice') + # dunning_level = fields.Integer(string='Dunning Level', default=30, help='30 hari sebelum jatuh tempo invoice') + + def generate_dunning_line(self): + if self.partner_id.parent_id: + raise UserError('Harus pilih parent company') + + partners = [] + partners += self.partner_id.child_ids + partners.append(self.partner_id) + + for partner in partners: + query = [ + ('move_type', '=', 'out_invoice'), + ('partner_id', '=', partner.id), + ('outstanding_amount', '>', 0), + ] + invoices = self.env['account.move'].search(query, order='invoice_date') + for invoice in invoices: + parameter_line = { + 'dunning_id': self.id, + 'partner_id': invoice.partner_id, + 'invoice_id': invoice.id, + 'date_invoice': invoice.invoice_date, + 'efaktur_id': invoice.efaktur_id, + 'reference': invoice.ref, + 'open_amt': invoice.outstanding_amount + } + self.env['dunning.run.line'].create([parameter_line]) + + @api.model + def create(self, vals): + vals['number'] = self.env['ir.sequence'].next_by_code('dunning.run') or '0' + result = super(DunningRun, self).create(vals) + return result def generate_dunning_line(self): # validation if not self.partner_id: raise UserError('Customer harus diisi') - if self.dunning_level <= 0: - raise UserError('Dunning Level harus diisi lebih dari 0') invoices = self.env['account.move'].search([ ('amount_residual_signed', '>', 0), - ('partner_id', '=', self.partner_id), + ('partner_id', '=', self.partner_id.id), ('move_type', '=', 'out_invoice'), ('state', '=', 'posted'), ]) @@ -35,11 +66,14 @@ class DunningRun(models.Model): for invoice in invoices: self.env['dunning.run.line'].create([{ 'dunning_id': self.id, + 'partner_id': invoice.partner_id.id, 'invoice_id': invoice.id, 'date_invoice': invoice.invoice_date, - 'efaktur_id': invoice.efaktur_id, + 'efaktur_id': invoice.efaktur_id.id, 'reference': invoice.ref, - 'open_amt': invoice.amount_residual_signed + 'total_amt': invoice.amount_total, + 'open_amt': invoice.amount_residual_signed, + 'due_date': invoice.invoice_date_due }]) count += 1 _logger.info("Dunning Line generated %s" % count) @@ -51,10 +85,13 @@ class DunningRunLine(models.Model): _order = 'dunning_id, id' dunning_id = fields.Many2one('dunning.run', string='Dunning Ref', required=True, ondelete='cascade', index=True, copy=False) + partner_id = fields.Many2one('res.partner', string='Customer') invoice_id = fields.Many2one('account.move', string='Invoice') date_invoice = fields.Date(string='Invoice Date') # due_date = fields.Date(string='Due Date') efaktur_id = fields.Many2one('vit.efaktur', string='Faktur Pajak') reference = fields.Char(string='Reference') + total_amt = fields.Float(string='Total Amount') open_amt = fields.Float(string='Open Amount') + due_date = fields.Date(string='Due Date') diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index dbbd4ad4..9f0410f4 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -44,6 +44,8 @@ class ProductTemplate(models.Model): usage = fields.Char(string='Usage') specification = fields.Char(string='Specification') material = fields.Char(string='Material') + is_new_product = fields.Boolean(string='Produk Baru', + help='Centang jika ingin ditammpilkan di website sebagai segment Produk Baru') # def write(self, vals): # if 'solr_flag' not in vals and self.solr_flag == 1: diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py new file mode 100644 index 00000000..403245fb --- /dev/null +++ b/indoteknik_custom/models/res_partner.py @@ -0,0 +1,7 @@ +from odoo import models, fields + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + reference_number = fields.Char(string="Reference Number") diff --git a/indoteknik_custom/models/x_manufactures.py b/indoteknik_custom/models/x_manufactures.py index 1d215cf8..e6842797 100755 --- a/indoteknik_custom/models/x_manufactures.py +++ b/indoteknik_custom/models/x_manufactures.py @@ -42,6 +42,8 @@ class XManufactures(models.Model): ('reset', 'Reset'), ('done', 'Done') ], string="Cache Reset") + sequence = fields.Integer(string='Sequence', help='Urutan tampil di homepage jika show as new product') + show_as_new_product = fields.Boolean(string='Show as New Product', help='Centang jika ingin ditammpilkan di website sebagai segment Produk Baru') def cache_reset(self): manufactures = self.env['x_manufactures'].search([ diff --git a/indoteknik_custom/report/report_invoice.xml b/indoteknik_custom/report/report_invoice.xml new file mode 100644 index 00000000..996dcf3e --- /dev/null +++ b/indoteknik_custom/report/report_invoice.xml @@ -0,0 +1,4 @@ +<odoo> + <template id="report_invoice_dunning" inherit_id="account.report_invoice_document"> + </template> +</odoo> diff --git a/indoteknik_custom/views/dunning_run.xml b/indoteknik_custom/views/dunning_run.xml index b18748ea..ab01d476 100644 --- a/indoteknik_custom/views/dunning_run.xml +++ b/indoteknik_custom/views/dunning_run.xml @@ -9,7 +9,6 @@ <field name="number"/> <field name="dunning_date"/> <field name="partner_id"/> - <field name="dunning_level"/> </tree> </field> </record> @@ -19,11 +18,14 @@ <field name="model">dunning.run.line</field> <field name="arch" type="xml"> <tree> + <field name="partner_id"/> <field name="invoice_id"/> <field name="date_invoice"/> <field name="efaktur_id"/> <field name="reference"/> + <field name="total_amt"/> <field name="open_amt"/> + <field name="due_date"/> </tree> </field> </record> @@ -39,7 +41,7 @@ <group> <field name="number"/> <field name="partner_id"/> - <field name="dunning_level"/> + <field name="dunning_date"/> <button name="generate_dunning_line" string="Generate" type="object" diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml index df4a5a22..6a6f474d 100644 --- a/indoteknik_custom/views/ir_sequence.xml +++ b/indoteknik_custom/views/ir_sequence.xml @@ -20,5 +20,15 @@ <field name="number_next">1</field> <field name="number_increment">1</field> </record> + + <record id="sequence_dunning_run" model="ir.sequence"> + <field name="name">Dunning Run</field> + <field name="code">dunning.run</field> + <field name="active">TRUE</field> + <field name="prefix">TF/%(year)s/</field> + <field name="padding">5</field> + <field name="number_next">1</field> + <field name="number_increment">1</field> + </record> </data> </odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml new file mode 100644 index 00000000..673718c4 --- /dev/null +++ b/indoteknik_custom/views/res_partner.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <data> + <record id="partner_form_view_inherit" model="ir.ui.view"> + <field name="name">Partner</field> + <field name="model">res.partner</field> + <field name="inherit_id" ref="base.view_partner_form"/> + <field name="arch" type="xml"> + <field name="vat" position="after"> + <field name="reference_number"/> + </field> + </field> + </record> + </data> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/x_manufactures.xml b/indoteknik_custom/views/x_manufactures.xml index d122c6c1..c7cedd9c 100755 --- a/indoteknik_custom/views/x_manufactures.xml +++ b/indoteknik_custom/views/x_manufactures.xml @@ -16,13 +16,14 @@ <field name="model">x_manufactures</field> <field name="arch" type="xml"> <tree> - <field name="id"/> <field name="x_name"/> <field name="x_negara_asal"/> <field name="x_short_desc"/> <field name="x_manufacture_level"/> <field name="x_manufacture_service_center"/> <field name="cache_reset_status"/> + <field name="show_as_new_product"/> + <field name="sequence"/> </tree> </field> </record> @@ -42,6 +43,8 @@ <field name="x_manufacture_level"/> <field name="x_produk_aksesoris_sparepart"/> <field name="cache_reset_status"/> + <field name="show_as_new_product"/> + <field name="sequence"/> </group> <group> <field name="x_logo_manufacture" widget="image"/> @@ -54,7 +57,16 @@ <field name="x_description"/> </page> <page string="Relasi Produk"> - <field name="x_manufacture_product"/> + <field name="x_manufacture_product" widget="section_and_note_one2many" mode="tree,kanban"> + <tree string="Products" editable="bottom"> + <field name="default_code"/> + <field name="name"/> + <field name="create_date"/> + <field name="solr_flag"/> + <field name="product_rating"/> + <field name="is_new_product"/> + </tree> + </field> </page> <page string="Relasi Banner"> <field name="x_manufactures_banners"/> |
