summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMqdd <ahmadmiqdad27@gmail.com>2025-12-15 13:31:39 +0700
committerMqdd <ahmadmiqdad27@gmail.com>2025-12-15 13:31:39 +0700
commit18d1a2c15b6cf198b275d80596f52cc44da00e3e (patch)
treeaf8efe03013711afb0bda2d34275aa4dea44a641
parent097f53b8cb0b2c39fb14f5f3a665410df2c7ebf3 (diff)
parent52066bed7e68757247e17ec89d31959247991595 (diff)
Merge branch 'odoo-backup' of https://bitbucket.org/altafixco/indoteknik-addons into cr_renca_find
merge
-rw-r--r--indoteknik_api/controllers/api_v1/stock_picking.py121
-rw-r--r--indoteknik_custom/models/stock_inventory.py4
-rw-r--r--indoteknik_custom/models/stock_picking.py21
-rw-r--r--indoteknik_custom/models/tukar_guling.py23
-rw-r--r--indoteknik_custom/models/user_pengajuan_tempo_request.py6
-rw-r--r--indoteknik_custom/report/purchase_report.xml4
-rw-r--r--indoteknik_custom/views/stock_picking.xml25
-rw-r--r--indoteknik_custom/views/tukar_guling.xml3
8 files changed, 176 insertions, 31 deletions
diff --git a/indoteknik_api/controllers/api_v1/stock_picking.py b/indoteknik_api/controllers/api_v1/stock_picking.py
index c19812f5..e33d01c1 100644
--- a/indoteknik_api/controllers/api_v1/stock_picking.py
+++ b/indoteknik_api/controllers/api_v1/stock_picking.py
@@ -121,57 +121,141 @@ class StockPicking(controller.Controller):
return self.response(picking.get_tracking_detail())
- @http.route(prefix + 'stock-picking/<scanid>/documentation', auth='public', methods=['PUT', 'OPTIONS'], csrf=False)
+ @http.route(prefix + 'stock-picking/<scanid>/documentation',
+ auth='public', methods=['PUT', 'OPTIONS'], csrf=False)
@controller.Controller.must_authorized()
def write_partner_stock_picking_documentation(self, scanid, **kw):
- paket_document = kw.get('paket_document') if 'paket_document' in kw else None
- dispatch_document = kw.get('dispatch_document') if 'dispatch_document' in kw else None
- self_pu = kw.get('self_pu') if 'self_pu' in kw else None
- # ===== Cari picking by id / picking_code =====
+ env = request.env
+ Picking = env['stock.picking'].sudo()
+ SjDoc = env['stock.picking.sj.document'].sudo()
+
+ paket_document = kw.get('paket_document')
+ dispatch_document = kw.get('dispatch_document')
+ self_pu = kw.get('self_pu')
+
+ # ===== Cari picking (FAST PATH) =====
picking = False
- if scanid.isdigit() and int(scanid) < 2147483646:
- picking = request.env['stock.picking'].search([('id', '=', int(scanid))], limit=0)
- if not picking:
- picking = request.env['stock.picking'].search([('picking_code', '=', scanid)], limit=0)
+ if scanid.isdigit():
+ picking = Picking.browse(int(scanid))
+ if not picking.exists():
+ picking = False
+
if not picking:
- return self.response(code=403, description='picking not found')
+ picking = Picking.search([('picking_code', '=', scanid)], limit=1)
+ if not picking:
+ return self.response(code=403, description='picking not found')
- # ===== Ambil MULTIPLE SJ dari form: sj_documentations=...&sj_documentations=... =====
+ # ===== Ambil SJ list =====
form = request.httprequest.form or {}
- sj_list = form.getlist('sj_documentations') # list of base64 strings
+ sj_list = form.getlist('sj_documentations')
- # fallback: kalau FE kirim single dengan nama yang sama (bukan list)
- if not sj_list and 'sj_documentations' in kw and kw.get('sj_documentations'):
+ if not sj_list and kw.get('sj_documentations'):
sj_list = [kw.get('sj_documentations')]
+ # ===== Prepare write params =====
params = {}
+ now = fields.Datetime.now()
+
if paket_document:
params['paket_documentation'] = paket_document
- params['driver_arrival_date'] = datetime.utcnow()
+ params['driver_arrival_date'] = now
+
if dispatch_document:
params['dispatch_documentation'] = dispatch_document
+
if sj_list and self_pu:
- params['driver_arrival_date'] = datetime.utcnow()
+ params['driver_arrival_date'] = now
if params:
picking.write(params)
+ # ===== BULK CREATE SJ (BIG WIN) =====
if sj_list:
- Child = request.env['stock.picking.sj.document'].sudo()
seq = (picking.sj_documentations[:1].sequence or 10) if picking.sj_documentations else 10
+ vals_list = []
+
for b64 in sj_list:
if not b64:
continue
- Child.create({
+ vals_list.append({
'picking_id': picking.id,
'sequence': seq,
'image': b64,
})
seq += 10
+ if vals_list:
+ SjDoc.create(vals_list)
+
return self.response({'name': picking.name})
+
+ # @http.route(prefix + 'stock-picking/<scanid>/documentation', auth='public', methods=['PUT', 'OPTIONS'], csrf=False)
+ # @controller.Controller.must_authorized()
+ # def write_partner_stock_picking_documentation(self, scanid, **kw):
+ # paket_document = kw.get('paket_document') if 'paket_document' in kw else None
+ # dispatch_document = kw.get('dispatch_document') if 'dispatch_document' in kw else None
+ # self_pu = kw.get('self_pu') if 'self_pu' in kw else None
+
+ # # ===== Cari picking by id / picking_code =====
+ # picking = False
+ # # if scanid.isdigit() and int(scanid) < 2147483646:
+ # # picking = request.env['stock.picking'].search([('id', '=', int(scanid))], limit=1)
+ # # if not picking:
+ # # picking = request.env['stock.picking'].search([('picking_code', '=', scanid)], limit=1)
+
+ # if scanid.isdigit():
+ # picking = request.env['stock.picking'].browse(int(scanid))
+ # if not picking.exists():
+ # picking = False
+
+ # if not picking:
+ # picking = request.env['stock.picking'].search(
+ # [('picking_code', '=', scanid)],
+ # limit=1
+ # )
+ # if not picking:
+ # return self.response(code=403, description='picking not found')
+
+ # # ===== Ambil MULTIPLE SJ dari form: sj_documentations=...&sj_documentations=... =====
+ # form = request.httprequest.form or {}
+ # sj_list = form.getlist('sj_documentations') # list of base64 strings
+
+ # # fallback: kalau FE kirim single dengan nama yang sama (bukan list)
+ # if not sj_list and 'sj_documentations' in kw and kw.get('sj_documentations'):
+ # sj_list = [kw.get('sj_documentations')]
+
+ # params = {}
+ # if paket_document:
+ # params['paket_documentation'] = paket_document
+ # params['driver_arrival_date'] = datetime.utcnow()
+ # if dispatch_document:
+ # params['dispatch_documentation'] = dispatch_document
+ # if sj_list and self_pu:
+ # params['driver_arrival_date'] = datetime.utcnow()
+
+ # if params:
+ # picking.write(params)
+
+
+ # vals_list = []
+ # for b64 in sj_list:
+ # if not b64:
+ # continue
+ # vals_list.append({
+ # 'picking_id': picking.id,
+ # 'sequence': seq,
+ # 'image': b64,
+ # })
+ # seq += 10
+
+ # if vals_list:
+ # Child.create(vals_list)
+
+
+ # return self.response({'name': picking.name})
+
# @http.route(prefix + 'stock-picking/<scanid>/documentation', auth='public', methods=['PUT', 'OPTIONS'], csrf=False)
# @controller.Controller.must_authorized()
# def write_partner_stock_picking_documentation(self, scanid, **kw):
@@ -306,4 +390,3 @@ class StockPicking(controller.Controller):
"waybill_id": data.get("courier_waybill_id")
}
)
-
diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py
index 432d9225..84eb5a17 100644
--- a/indoteknik_custom/models/stock_inventory.py
+++ b/indoteknik_custom/models/stock_inventory.py
@@ -53,8 +53,8 @@ class StockInventory(models.Model):
return "00001" # Jika belum ada data, mulai dari 00001
def action_start(self):
- if self.env.user.id not in [21, 17, 6277]:
- raise UserError("Hanya Rafly, denise, dan faisal yang bisa start inventory")
+ if self.env.user.id not in [21, 17, 571, 28]:
+ raise UserError("Hanya Rafly, Denise, Iqmal, dan Stephan yang bisa start inventory")
return super(StockInventory, self).action_start()
@api.model
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index 2f99a85a..2465fa96 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -202,6 +202,7 @@ class StockPicking(models.Model):
so_num = fields.Char('SO Number', compute='_get_so_num')
is_so_fiktif = fields.Boolean('SO Fiktif?', compute='_compute_is_so_fiktif', tracking=3)
payment_term = fields.Char('Payment Term', compute='_get_partner_payment_term')
+ is_rev_tg = fields.Boolean('Administrasi')
@api.depends('sale_id.payment_term_id')
def _get_partner_payment_term(self):
@@ -1453,6 +1454,24 @@ class StockPicking(models.Model):
raise UserError(
f"Tidak bisa validasi {picking.name} sebelum {prev_picking.name} divalidasi."
)
+
+ def internal_transfer_val(self):
+ for rec in self:
+ # Gudang service
+ if rec.location_dest_id.id == 98 and self.env.user.id not in [21, 17]:
+ raise UserError(f"Transfer ke gudang {rec.location_dest_id.name} harus di approve Rafly H. atau Denise")
+ # Gudang selisih
+ if rec.location_dest_id.id == 47 and self.env.user.id not in [21, 17]:
+ raise UserError(f"Transfer ke gudang {rec.location_dest_id.name} harus di approve Rafly H. atau Denise")
+
+ # Gudang Rusak
+ if rec.location_dest_id.id == 62 and self.env.user.id not in [21, 17]:
+ raise UserError(f"Transfer ke gudang {rec.location_dest_id.name} harus di approve Rafly H. atau Denise")
+
+ # Gudang Peminjaman
+ if rec.location_dest_id.id == 48 and self.env.user.id not in [21, 17]:
+ raise UserError(f"Transfer ke gudang {rec.location_dest_id.name} harus di approve Rafly H. atau Denise")
+
def button_validate(self):
self.check_invoice_date()
_logger.info("Kode Picking: %s", self.picking_type_id.code)
@@ -1463,6 +1482,8 @@ class StockPicking(models.Model):
group_id = self.env.ref('indoteknik_custom.group_role_merchandiser').id
users_in_group = self.env['res.users'].search([('groups_id', 'in', [group_id])])
active_model = self.env.context.get('active_model')
+ if self.picking_type_id.id in [26, 10, 20, 32, 53, 52]:
+ self.internal_transfer_val()
if self.tukar_guling_po_id and self.tukar_guling_po_id.return_type == 'tukar_guling':
self.validate_seq_vcm()
if self.is_so_fiktif == True:
diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py
index f31c68d0..682c478a 100644
--- a/indoteknik_custom/models/tukar_guling.py
+++ b/indoteknik_custom/models/tukar_guling.py
@@ -87,6 +87,7 @@ class TukarGuling(models.Model):
is_has_invoice = fields.Boolean('Has Invoice?', compute='_compute_is_has_invoice', readonly=True, default=False)
invoice_id = fields.Many2many('account.move', string='Invoice Ref', readonly=True)
+ rev_tukar_guling = fields.Boolean('Administrasi?', tracking=3)
@api.depends('origin', 'operations')
def _compute_origin_so(self):
@@ -808,7 +809,9 @@ class TukarGuling(models.Model):
srt_picking.write({
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
- 'sale_order': record.origin
+ 'sale_order': record.origin,
+ 'note': record.notes,
+ 'is_rev_tg': bool(record.rev_tukar_guling),
})
created_returns.append(srt_picking)
_logger.info(f"✅ SRT created: {srt_picking.name}")
@@ -868,7 +871,12 @@ class TukarGuling(models.Model):
ort_picking.write({
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
- 'sale_order': record.origin
+ 'sale_order': record.origin,
+ 'sj_return_date': bu_out.sj_return_date,
+ 'driver_arrival_date': bu_out.driver_arrival_date,
+ 'delivery_date': bu_out.delivery_date,
+ 'note': record.notes,
+ 'is_rev_tg': bool(record.rev_tukar_guling),
})
created_returns.append(ort_picking)
@@ -913,7 +921,9 @@ class TukarGuling(models.Model):
new_pick.write({
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
- 'sale_order': record.origin
+ 'sale_order': record.origin,
+ 'note': record.notes,
+ 'is_rev_tg': bool(record.rev_tukar_guling),
})
new_pick.action_assign()
new_pick.action_confirm()
@@ -952,7 +962,12 @@ class TukarGuling(models.Model):
new_out.write({
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
- 'sale_order': record.origin
+ 'sale_order': record.origin,
+ 'note': record.notes,
+ 'sj_return_date': bu_out.sj_return_date if record.rev_tukar_guling else False,
+ 'driver_arrival_date': bu_out.driver_arrival_date if record.rev_tukar_guling else False,
+ 'delivery_date': bu_out.delivery_date if record.rev_tukar_guling else False,
+ 'is_rev_tg': bool(record.rev_tukar_guling),
})
created_returns.append(new_out)
_logger.info(f"✅ BU/OUT Baru dari SRT created: {new_out.name}")
diff --git a/indoteknik_custom/models/user_pengajuan_tempo_request.py b/indoteknik_custom/models/user_pengajuan_tempo_request.py
index 6e8498f7..6a553946 100644
--- a/indoteknik_custom/models/user_pengajuan_tempo_request.py
+++ b/indoteknik_custom/models/user_pengajuan_tempo_request.py
@@ -46,7 +46,7 @@ class UserPengajuanTempoRequest(models.Model):
user_id = fields.Many2one('res.partner', string='User')
user_company_id = fields.Many2one('res.partner', string='Company')
pengajuan_tempo_id = fields.Many2one('user.pengajuan.tempo', string='Form Tempo')
- tempo_duration = fields.Many2one('account.payment.term', string='Durasi Tempo', tracking=3, domain=[('id', 'in', [24, 25, 29, 32])])
+ tempo_duration = fields.Many2one('account.payment.term', string='Durasi Tempo', tracking=3)
tempo_limit = fields.Integer(string='Limit Tempo', tracking=3)
state_tempo = fields.Selection([
('draft', 'Pengajuan Tempo'),
@@ -91,7 +91,7 @@ class UserPengajuanTempoRequest(models.Model):
website_tempo = fields.Char(string='Website', related='pengajuan_tempo_id.website_tempo', store=True, tracking=True, readonly=False)
portal = fields.Boolean(string='Portal Website', related='pengajuan_tempo_id.portal', store=True, tracking=True, readonly=False)
estimasi_tempo = fields.Char(string='Estimasi Pembelian Pertahun', related='pengajuan_tempo_id.estimasi_tempo', store=True, tracking=True, readonly=False)
- tempo_duration_origin = fields.Many2one('account.payment.term', string='Durasi Tempo', related='tempo_duration', store=True, tracking=True, readonly=False, domain=[('id', 'in', [24, 25, 29, 32])])
+ tempo_duration_origin = fields.Many2one('account.payment.term', string='Durasi Tempo', related='tempo_duration', store=True, tracking=True, readonly=False)
tempo_limit_origin = fields.Char(string='Limit Tempo', related='pengajuan_tempo_id.tempo_limit' , store=True, tracking=True, readonly=False)
category_produk_ids = fields.Many2many('product.public.category', string='Kategori Produk yang Digunakan', related='pengajuan_tempo_id.category_produk_ids', readonly=False)
@@ -688,4 +688,4 @@ class UserPengajuanTempoRequest(models.Model):
def format_currency(self, number):
number = int(number)
- return "{:,}".format(number).replace(',', '.') \ No newline at end of file
+ return "{:,}".format(number).replace(',', '.')
diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml
index d3509720..54ac6193 100644
--- a/indoteknik_custom/report/purchase_report.xml
+++ b/indoteknik_custom/report/purchase_report.xml
@@ -105,8 +105,8 @@
<!-- TEKS -->
<div style="display:flex; flex-direction:column; flex:1;">
<span style="font-weight:bold; margin-bottom:2px;">
- <t t-esc="line_index + 1"/>.
- <t t-if="line.product_id.id == 114360">
+ <t t-esc="line_index + 1"/>.
+ <t t-if="line.product_id.id in [114360, 595346, 610166]">
<t t-esc="line.name"/>
</t>
<t t-else="">
diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml
index e1d9bd1f..1bb7174e 100644
--- a/indoteknik_custom/views/stock_picking.xml
+++ b/indoteknik_custom/views/stock_picking.xml
@@ -20,6 +20,8 @@
<field name="sj_return_date" optional="hide"/>
<field name="date_reserved" optional="hide"/>
<field name="state_reserve" optional="hide"/>
+ <field name="linked_out_picking_id" optional="hide"/>
+ <field name="linked_manual_bu_out" optional="hide"/>
<field name="state_packing" widget="badge" decoration-success="state_packing == 'packing_done'"
decoration-danger="state_packing == 'not_packing'" optional="hide"/>
<field name="final_seq"/>
@@ -171,6 +173,8 @@
<field name="invoice_status"/>
<field name="is_bu_iu"/>
<field name="is_so_fiktif" readonly="1"/>
+ <field name="is_rev_tg" invisible="1" />
+ <field name="tukar_guling_id" invisible="1" />
<field name="approval_status" attrs="{'invisible': [('is_bu_iu', '=', False)]}"/>
<field name="date_doc_kirim" attrs="{'readonly':[('invoice_status', '=', 'invoiced')]}"/>
<field name="summary_qty_operation"/>
@@ -356,6 +360,27 @@
title="FIKTIF"
bg_color="bg-danger"
attrs="{'invisible': [('is_so_fiktif', '=', False)]}"/>
+ <widget name="web_ribbon"
+ title="Administrasi"
+ bg_color="bg-danger"
+ attrs="{
+ 'invisible': [
+ '|','|',
+ ('tukar_guling_id', '=', False),
+ ('is_rev_tg', '=', False),
+ ('picking_type_id', 'not in', [29, 30])
+ ]}"/>
+
+ <widget name="web_ribbon"
+ title="Perlu Dikirim"
+ bg_color="bg-success"
+ attrs="{
+ 'invisible': [
+ '|','|',
+ ('tukar_guling_id', '=', False),
+ ('is_rev_tg', '=', True),
+ ('picking_type_id', 'not in', [29, 30])
+ ]}"/>
</xpath>
</field>
</record>
diff --git a/indoteknik_custom/views/tukar_guling.xml b/indoteknik_custom/views/tukar_guling.xml
index 9dd31905..8cfb5680 100644
--- a/indoteknik_custom/views/tukar_guling.xml
+++ b/indoteknik_custom/views/tukar_guling.xml
@@ -85,6 +85,7 @@
attrs="{'readonly': [('state', 'not in', 'draft')]}"/>
<!-- <field name="origin" readonly="1"/>-->
<field name="origin_so" readonly="1"/>
+ <field name="rev_tukar_guling" attrs="{'invisible': [('return_type', '!=', 'tukar_guling')]}"/>
<field name="is_has_invoice" readonly="1"/>
</group>
<group>
@@ -133,4 +134,4 @@
</field>
</record>
</data>
-</odoo> \ No newline at end of file
+</odoo>