summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-05-15 16:22:21 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-05-15 16:22:21 +0700
commitf4f150ec2492b048886e1965a0a650864295c76c (patch)
tree37386674983c542d6730e993e09337505dfc415e
parent6364f3d0bec6e75e3056caa928bbe11d39cc145f (diff)
grand total field, compute grand total, sale order print for website, fix sale order download pdf api
-rw-r--r--indoteknik_api/controllers/api_v1/sale_order.py10
-rw-r--r--indoteknik_api/models/sale_order.py3
-rwxr-xr-xindoteknik_custom/__manifest__.py3
-rwxr-xr-xindoteknik_custom/models/sale_order.py5
-rw-r--r--indoteknik_custom/report/report_sale_order.xml273
-rwxr-xr-xindoteknik_custom/views/sale_order.xml1
6 files changed, 290 insertions, 5 deletions
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py
index ec39b32a..8fe1bb52 100644
--- a/indoteknik_api/controllers/api_v1/sale_order.py
+++ b/indoteknik_api/controllers/api_v1/sale_order.py
@@ -187,7 +187,7 @@ class SaleOrder(controller.Controller):
return self.response('Unauthorized')
sale_order = request.env['sale.order'].sudo().search_read([('id', '=', id)], ['name'])
- pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'sale.report_saleorder')])._render_qweb_pdf([id])
+ pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'indoteknik_custom.report_saleorder_website')])._render_qweb_pdf([id])
if pdf and len(sale_order) > 0:
return rest_api.response_attachment({
'content': pdf,
@@ -235,7 +235,9 @@ class SaleOrder(controller.Controller):
'po_number': [],
'po_file': [],
'type': [],
- 'delivery_amount': ['number', 'default:0']
+ 'delivery_amount': ['number', 'default:0'],
+ 'carrier_id': [],
+ 'delivery_service_type': []
})
if not params['valid']:
@@ -260,7 +262,9 @@ class SaleOrder(controller.Controller):
'partner_purchase_order_file': params['value']['po_file'],
'delivery_amt': params['value']['delivery_amount'],
'shipping_cost_covered': 'customer',
- 'shipping_paid_by': 'customer'
+ 'shipping_paid_by': 'customer',
+ 'carrier_id': params['value']['carrier_id'],
+ 'delivery_service_type': params['value']['delivery_service_type'],
}
if params['value']['type'] == 'sale_order':
parameters['approval_status'] = 'pengajuan1'
diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py
index cadf9f77..9661a0ba 100644
--- a/indoteknik_api/models/sale_order.py
+++ b/indoteknik_api/models/sale_order.py
@@ -12,7 +12,7 @@ class SaleOrder(models.Model):
'sales': sale_order.user_id.name,
'amount_untaxed': sale_order.amount_untaxed,
'amount_tax': sale_order.amount_tax,
- 'amount_total': sale_order.amount_total,
+ 'amount_total': sale_order.grand_total,
'purchase_order_name': sale_order.partner_purchase_order_name or sale_order.client_order_ref,
'purchase_order_file': True if sale_order.partner_purchase_order_file else False,
'invoice_count': sale_order.invoice_count,
@@ -49,6 +49,7 @@ class SaleOrder(models.Model):
data_with_detail = {
'payment_term': sale_order.payment_term_id.name or '',
'products': [],
+ 'delivery_amount': sale_order.delivery_amt or 0,
'address': {
'customer': res_users.api_address_response(sale_order.partner_id),
'invoice': res_users.api_address_response(sale_order.partner_invoice_id),
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index d9e98975..c52e27b7 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -79,7 +79,8 @@
'report/report_banner_banner2.xml',
'report/purchase_order.xml',
'report/report_invoice.xml',
- 'report/report_picking.xml'
+ 'report/report_picking.xml',
+ 'report/report_sale_order.xml',
],
'demo': [],
'css': [],
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 69e96968..14c87641 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -73,6 +73,7 @@ class SaleOrder(models.Model):
gross_amount = fields.Float(string='Gross Amount', help='Jumlah pembayaran yang dilakukan dengan Midtrans')
notification = fields.Char(string='Notification', help='Dapat membantu error dari approval')
delivery_service_type = fields.Char(string='Delivery Service Type', help='data dari rajaongkir')
+ grand_total = fields.Monetary(string='Grand Total', help='Amount total + amount delivery', compute='_compute_grand_total')
@api.model
def _generate_so_access_token(self, limit=50):
@@ -362,6 +363,10 @@ class SaleOrder(models.Model):
for line in self.order_line:
line.product_id_change()
+ def _compute_grand_total(self):
+ for order in self:
+ order.grand_total = order.delivery_amt + order.amount_total
+
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
diff --git a/indoteknik_custom/report/report_sale_order.xml b/indoteknik_custom/report/report_sale_order.xml
new file mode 100644
index 00000000..595a989f
--- /dev/null
+++ b/indoteknik_custom/report/report_sale_order.xml
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data>
+ <record id="action_report_saleorder_website" model="ir.actions.report">
+ <field name="name">Quotation / Order (Website)</field>
+ <field name="model">sale.order</field>
+ <field name="report_type">qweb-pdf</field>
+ <field name="report_name">indoteknik_custom.report_saleorder_website</field>
+ <field name="report_file">indoteknik_custom.report_saleorder_website</field>
+ <field name="print_report_name">(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name)</field>
+ <field name="binding_model_id" ref="model_sale_order"/>
+ <field name="binding_type">report</field>
+ </record>
+ </data>
+
+ <template id="report_saleorder_website">
+ <t t-call="web.html_container">
+ <t t-foreach="docs" t-as="doc">
+ <t t-call="indoteknik_custom.report_saleorder_website_document" t-lang="doc.partner_id.lang"/>
+ </t>
+ </t>
+ </template>
+
+ <template id="report_saleorder_website_document">
+ <t t-call="web.external_layout">
+ <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
+ <t t-set="address">
+ <div t-field="doc.partner_id"
+ t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
+ <p t-if="doc.partner_id.vat"><t t-esc="doc.company_id.country_id.vat_label or 'Tax ID'"/>: <span t-field="doc.partner_id.vat"/></p>
+ </t>
+ <t t-if="doc.partner_shipping_id == doc.partner_invoice_id
+ and doc.partner_invoice_id != doc.partner_id
+ or doc.partner_shipping_id != doc.partner_invoice_id">
+ <t t-set="information_block">
+ <strong t-if="doc.partner_shipping_id == doc.partner_invoice_id">Invoicing and Shipping Address:</strong>
+ <strong t-if="doc.partner_shipping_id != doc.partner_invoice_id">Invoicing Address:</strong>
+ <div t-field="doc.partner_invoice_id"
+ t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'/>
+ <t t-if="doc.partner_shipping_id != doc.partner_invoice_id">
+ <strong>Shipping Address:</strong>
+ <div t-field="doc.partner_shipping_id"
+ t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'/>
+ </t>
+ </t>
+ </t>
+ <div class="page">
+ <div class="oe_structure"/>
+
+ <h2 class="mt16">
+ <t t-if="not (env.context.get('proforma', False) or is_pro_forma)">
+ <span t-if="doc.state not in ['draft','sent']">Order # </span>
+ <span t-if="doc.state in ['draft','sent']">Quotation # </span>
+ </t>
+ <t t-if="env.context.get('proforma', False) or is_pro_forma">
+ <span>Pro-Forma Invoice # </span>
+ </t>
+ <span t-field="doc.name"/>
+ </h2>
+
+ <div class="row mt32 mb32" id="informations">
+ <div t-if="doc.client_order_ref" class="col-auto col-3 mw-100 mb-2">
+ <strong>Your Reference:</strong>
+ <p class="m-0" t-field="doc.client_order_ref"/>
+ </div>
+ <div t-if="doc.date_order and doc.state not in ['draft','sent']" class="col-auto col-3 mw-100 mb-2">
+ <strong>Order Date:</strong>
+ <p class="m-0" t-field="doc.date_order"/>
+ </div>
+ <div t-if="doc.date_order and doc.state in ['draft','sent']" class="col-auto col-3 mw-100 mb-2">
+ <strong>Quotation Date:</strong>
+ <p class="m-0" t-field="doc.date_order" t-options='{"widget": "date"}'/>
+ </div>
+ <div t-if="doc.validity_date and doc.state in ['draft', 'sent']" class="col-auto col-3 mw-100 mb-2" name="expiration_date">
+ <strong>Expiration:</strong>
+ <p class="m-0" t-field="doc.validity_date"/>
+ </div>
+ <div t-if="doc.user_id.name" class="col-auto col-3 mw-100 mb-2">
+ <strong>Salesperson:</strong>
+ <p class="m-0" t-field="doc.user_id"/>
+ </div>
+ </div>
+
+ <!-- Is there a discount on at least one line? -->
+ <t t-set="display_discount" t-value="any(l.discount for l in doc.order_line)"/>
+
+ <table class="table table-sm o_main_table">
+ <!-- In case we want to repeat the header, remove "display: table-row-group" -->
+ <thead style="display: table-row-group">
+ <tr>
+ <th name="th_description" class="text-left">Description</th>
+ <th name="th_quantity" class="text-right">Quantity</th>
+ <th name="th_priceunit" class="text-right">Unit Price</th>
+ <th name="th_discount" t-if="display_discount" class="text-right" groups="product.group_discount_per_so_line">
+ <span>Disc.%</span>
+ </th>
+ <th name="th_taxes" class="text-right">Taxes</th>
+ <th name="th_subtotal" class="text-right">
+ <span groups="account.group_show_line_subtotals_tax_excluded">Amount</span>
+ <span groups="account.group_show_line_subtotals_tax_included">Total Price</span>
+ </th>
+ </tr>
+ </thead>
+ <tbody class="sale_tbody">
+
+ <t t-set="current_subtotal" t-value="0"/>
+
+ <t t-foreach="doc.order_line" t-as="line">
+
+ <t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
+ <t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
+
+ <tr t-att-class="'bg-200 font-weight-bold o_line_section' if line.display_type == 'line_section' else 'font-italic o_line_note' if line.display_type == 'line_note' else ''">
+ <t t-if="not line.display_type">
+ <td name="td_name"><span t-field="line.name"/></td>
+ <td name="td_quantity" class="text-right">
+ <span t-field="line.product_uom_qty"/>
+ <span t-field="line.product_uom"/>
+ </td>
+ <td name="td_priceunit" class="text-right">
+ <span t-field="line.price_unit"/>
+ </td>
+ <td t-if="display_discount" class="text-right" groups="product.group_discount_per_so_line">
+ <span t-field="line.discount"/>
+ </td>
+ <td name="td_taxes" class="text-right">
+ <span t-esc="', '.join(map(lambda x: (x.description or x.name), line.tax_id))"/>
+ </td>
+ <td name="td_subtotal" class="text-right o_price_total">
+ <span t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
+ <span t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
+ </td>
+ </t>
+ <t t-if="line.display_type == 'line_section'">
+ <td name="td_section_line" colspan="99">
+ <span t-field="line.name"/>
+ </td>
+ <t t-set="current_section" t-value="line"/>
+ <t t-set="current_subtotal" t-value="0"/>
+ </t>
+ <t t-if="line.display_type == 'line_note'">
+ <td name="td_note_line" colspan="99">
+ <span t-field="line.name"/>
+ </td>
+ </t>
+ </tr>
+
+ <t t-if="current_section and (line_last or doc.order_line[line_index+1].display_type == 'line_section')">
+ <tr class="is-subtotal text-right">
+ <td name="td_section_subtotal" colspan="99">
+ <strong class="mr16">Subtotal</strong>
+ <span
+ t-esc="current_subtotal"
+ t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'
+ />
+ </td>
+ </tr>
+ </t>
+ </t>
+ </tbody>
+ </table>
+
+ <div class="clearfix" name="so_total_summary">
+ <div id="total" class="row" name="total">
+ <div t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto">
+ <table class="table table-sm">
+ <tr class="border-black o_subtotal" style="">
+ <td name="td_amount_untaxed_label"><strong>Subtotal</strong></td>
+ <td name="td_amount_untaxed" class="text-right">
+ <span t-field="doc.amount_untaxed"/>
+ </td>
+ </tr>
+ <tr>
+ <td name="td_amount_total_label">Tax</td>
+ <td name="td_amount_total" class="text-right">
+ <span t-field="doc.amount_tax"/>
+ </td>
+ </tr>
+ <tr>
+ <td name="td_grand_total_label">Delivery Amount</td>
+ <td name="td_grand_total" class="text-right">
+ <span t-field="doc.delivery_amt" t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/>
+ </td>
+ </tr>
+ <tr class="border-black o_total">
+ <td name="td_grand_total_label"><strong>Grand Total</strong></td>
+ <td name="td_grand_total" class="text-right">
+ <span t-field="doc.grand_total"/>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+
+ <div t-if="doc.signature" class="mt32 ml64 mr4" name="signature">
+ <div class="offset-8">
+ <strong>Signature</strong>
+ </div>
+ <div class="offset-8">
+ <img t-att-src="image_data_uri(doc.signature)" style="max-height: 4cm; max-width: 8cm;"/>
+ </div>
+ <div class="offset-8 text-center">
+ <p t-field="doc.signed_by"/>
+ </div>
+ </div>
+
+ <div class="oe_structure"/>
+
+ <p t-field="doc.note" />
+ <p t-if="doc.payment_term_id.note">
+ <span t-field="doc.payment_term_id.note"/>
+ </p>
+ <p id="fiscal_position_remark" t-if="doc.fiscal_position_id and doc.fiscal_position_id.sudo().note">
+ <strong>Fiscal Position Remark:</strong>
+ <span t-field="doc.fiscal_position_id.sudo().note"/>
+ </p>
+ </div>
+ </t>
+ </template>
+
+ <template id="report_saleorder_website_document_inherit_sale_management" inherit_id="indoteknik_custom.report_saleorder_website_document">
+ <xpath expr="//div[@name='signature']" position="after">
+ <div t-if="doc.sale_order_option_ids and doc.state in ['draft', 'sent']">
+ <t t-set="has_option_discount" t-value="any(option.discount != 0.0 for option in doc.sale_order_option_ids)" />
+ <h4 name="h_optional_products">
+ <span>Options</span>
+ </h4>
+ <table name="table_optional_products" class="table table-sm">
+ <thead>
+ <tr>
+ <th name="th_option_name" class="text-left">Description</th>
+ <th t-if="has_option_discount" name="th_option_discount" groups="product.group_discount_per_so_line" class="text-left">Disc.%</th>
+ <th name="th_option_price_unit" class="text-right">Unit Price</th>
+ </tr>
+ </thead>
+ <tbody class="sale_tbody">
+ <tr t-foreach="doc.sale_order_option_ids" t-as="option">
+ <td name="td_option_name">
+ <span t-field="option.name"/>
+ </td>
+ <td t-if="has_option_discount" name="td_option_discount" groups="product.group_discount_per_so_line">
+ <strong t-if="option.discount != 0.0" class="text-info">
+ <t t-esc="((option.discount % 1) and '%s' or '%d') % option.discount"/>%
+ </strong>
+ </td>
+ <td name="td_option_price_unit">
+ <strong class="text-right">
+ <div t-field="option.price_unit"
+ t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'
+ t-att-style="option.discount and 'text-decoration: line-through' or None"
+ t-att-class="option.discount and 'text-danger' or None"/>
+ <div t-if="option.discount">
+ <t t-esc="'%.2f' % ((1-option.discount / 100.0) * option.price_unit)"/>
+ </div>
+ </strong>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </xpath>
+ </template>
+
+ <template id="report_saleorder_website_document_inherit_sale_stock" inherit_id="indoteknik_custom.report_saleorder_website_document">
+ <xpath expr="//div[@name='expiration_date']" position="after">
+ <div class="col-3" t-if="doc.incoterm" groups="sale_stock.group_display_incoterm">
+ <strong>Incoterm:</strong>
+ <p t-field="doc.incoterm.code"/>
+ </div>
+ </xpath>
+ </template>
+</odoo> \ No newline at end of file
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index fde93a9b..c66201a9 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -65,6 +65,7 @@
<field name="line_no" readonly="1"/>
</xpath>
<field name="amount_total" position="after">
+ <field name="grand_total"/>
<field name="total_margin"/>
<field name="total_percent_margin"/>
</field>