Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vcrpy
121 changes: 121 additions & 0 deletions website_sendcloud_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

===================
Sendcloud eCommerce
===================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:cf2ca1ed3d0a6af51578191e30c6489ca8e0f4aebfc6e469129dc49166c4ed63
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fe--commerce-lightgray.png?logo=github
:target: https://github.com/OCA/e-commerce/tree/17.0/website_sendcloud_oca
:alt: OCA/e-commerce
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/e-commerce-17-0/e-commerce-17-0-website_sendcloud_oca
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/e-commerce&target_branch=17.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module is part of the Sendcloud connector for Odoo.

At the moment, the Sendcloud connector for Odoo consists of two modules:
delivery_sendcloud_oca and website_sendcloud_oca.

1) delivery_sendcloud_oca. This module works for the backend.
2) website_sendcloud_oca. This module is for the frontend (webshop) and
it depends on delivery_sendcloud_oca.

Full documentation for developers is in https://docs.sendcloud.sc/.

**Table of contents**

.. contents::
:local:

Usage
=====

Quickstart
----------

In short this is how the module works:

- the customer selects some products in the online shop. The products
are added in the shopping Cart
- then the customer opens his shopping Cart and clicks on Process
Checkout
- the customer chooses one of the delivery method that Sendcloud
provides

Service Point Picker
--------------------

The module contains a link that opens the Service Point Picker
(javascript) in the website shopping Cart. The link is placed near the
selected Sendcloud Shipping Method. The link is visible in case:

- the configuration in the Sendcloud panel has the Service Point
flag to True (in the Sendcloud integration config)
- the Shipping Method selected in the picking is provided by
Sendcloud
- the Shipping Method has field sendcloud_service_point_input ==
"required"
- all the criteria (from country, to country, weight) match with the
current order
- the Shipping Method is set to "Published" in the website

Case of multiple shops
----------------------

TODO

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/e-commerce/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/e-commerce/issues/new?body=module:%20website_sendcloud_oca%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Onestein

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/e-commerce <https://github.com/OCA/e-commerce/tree/17.0/website_sendcloud_oca>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
3 changes: 3 additions & 0 deletions website_sendcloud_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import controllers
from . import models
from . import wizards
34 changes: 34 additions & 0 deletions website_sendcloud_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

{
"name": "Sendcloud eCommerce",
"summary": "Integrate your web shop with Sendcloud",
"images": ["static/description/sendcloud_cover.jpeg"],
"category": "Website/Website",
"version": "17.0.1.0.0",
"author": "Onestein, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/e-commerce",
"license": "LGPL-3",
"depends": ["website_sale", "delivery_sendcloud_oca"],
"data": [
"security/ir.model.access.csv",
"data/onboarding_data.xml",
"templates/website_sale_delivery.xml",
"views/res_config_settings_view.xml",
"wizards/sendcloud_sync_wizard_view.xml",
"wizards/sendcloud_website_brand_wizard_view.xml",
"views/sendcloud_onboarding_views.xml",
"views/menu.xml",
],
"assets": {
"web.assets_frontend": [
"website_sendcloud_oca/static/src/js/*",
"website_sendcloud_oca/static/src/xml/*",
],
"web.assets_tests": [
"website_sendcloud_oca/static/src/tests/**/*",
],
},
"application": True,
}
1 change: 1 addition & 0 deletions website_sendcloud_oca/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import main
37 changes: 37 additions & 0 deletions website_sendcloud_oca/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)
from odoo import http
from odoo.http import request

from odoo.addons.website_sale.controllers.delivery import WebsiteSaleDelivery


class WebsiteSaleSendcloudDelivery(WebsiteSaleDelivery):
def _update_website_sale_delivery_return(self, order, **post):
res = super()._update_website_sale_delivery_return(order, **post)
if order and post.get("carrier_id"):
carrier_id = int(post["carrier_id"])
carrier = request.env["delivery.carrier"].sudo().browse(carrier_id)
if carrier and carrier.delivery_type == "sendcloud":
res.update(order.sendcloud_sale_delivery_data(carrier))
return res

@http.route(
["/shop/sendcloud_update_service_point_address"],
type="json",
auth="public",
methods=["POST"],
website=True,
csrf=False,
)
def sendcloud_update_service_point_address(self, **post):
if post.get("order_id"):
order = request.env["sale.order"].sudo().browse(post.get("order_id"))
order.write(
{
"sendcloud_service_point_address": post.get(
"sendcloud_service_point_address"
)
}
)
return True
28 changes: 28 additions & 0 deletions website_sendcloud_oca/data/onboarding_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<!-- ONBOARDING STEPS -->
<!-- Sendcloud -->
<record id="onboarding_website_brand_step" model="onboarding.onboarding.step">
<field name="title">Configure Website Brands</field>
<field name="description">Set Sendcloud Website Brands.</field>
<field name="button_text">Configure</field>
<field name="done_text">Enjoy!</field>
<field
name="panel_step_open_action_name"
>action_open_sendcloud_onboarding_website_brand
</field>
</record>

<!-- ONBOARDING PANELS -->
<record
id="delivery_sendcloud_oca.onboarding_onboarding_sendcloud"
model="onboarding.onboarding"
>
<field
name="step_ids"
eval="[
Command.link(ref('onboarding_website_brand_step')),
]"
/>
</record>
</odoo>
5 changes: 5 additions & 0 deletions website_sendcloud_oca/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import delivery_carrier
from . import onboarding_onboarding_step
from . import sale_order
from . import sendcloud_parcel
from . import website
26 changes: 26 additions & 0 deletions website_sendcloud_oca/models/delivery_carrier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

from odoo import api, models


class DeliveryCarrier(models.Model):
_inherit = "delivery.carrier"

@api.model
def _sendcloud_publish_all_shipping_methods(self, company_id):
shipping_methods = self.search(
[("delivery_type", "=", "sendcloud"), ("company_id", "=", company_id)]
)
shipping_methods.write({"website_published": True})

@api.model
def sendcloud_sync_shipping_method(self):
res = super().sendcloud_sync_shipping_method()
for company in self.env["res.company"].search([]):
integration = company.sendcloud_default_integration_id
if integration and self.env.context.get(
"sendcloud_publish_all_shipping_methods"
):
self._sendcloud_publish_all_shipping_methods(company.id)
return res
14 changes: 14 additions & 0 deletions website_sendcloud_oca/models/onboarding_onboarding_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

from odoo import api, models


class OnboardingStep(models.Model):
_inherit = "onboarding.onboarding.step"

@api.model
def action_open_sendcloud_onboarding_website_brand(self):
"""Called by onboarding panel."""
action_name = "website_sendcloud_oca.action_sendcloud_onboarding_website_wizard"
return self.env.ref(action_name).read()[0]
51 changes: 51 additions & 0 deletions website_sendcloud_oca/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

from odoo import models


class SaleOrder(models.Model):
_inherit = "sale.order"

def _get_delivery_methods(self):
return super(
SaleOrder, self.with_context(sale_order_id=self.id)
)._get_delivery_methods()

def sendcloud_sale_delivery_data(self, carrier):
self.ensure_one()
self.write({"sendcloud_service_point_address": False})
return {
"sendcloud_details": {
"order_id": self.id,
"key": carrier.sendcloud_integration_id.public_key or "",
"country_code": self.partner_shipping_id.country_id.code or "",
"postcode": self.partner_id.zip or "",
"carrier_name": [carrier.sendcloud_carrier or ""],
}
}

def _check_carrier_quotation(self, force_carrier_id=None, keep_carrier=False):
self.ensure_one()
if (
not force_carrier_id
and self.partner_shipping_id.property_delivery_carrier_id
and not keep_carrier
):
force_carrier_id = self.partner_shipping_id.property_delivery_carrier_id.id
carrier = (
force_carrier_id
and self.env["delivery.carrier"].browse(force_carrier_id)
or self.carrier_id
)
if carrier:
res = carrier.rate_shipment(self)
if res.get("sendcloud_country_specific_product"):
self = self.with_context(
sendcloud_country_specific_product=res[
"sendcloud_country_specific_product"
]
)
return super()._check_carrier_quotation(
force_carrier_id=force_carrier_id, keep_carrier=keep_carrier
)
17 changes: 17 additions & 0 deletions website_sendcloud_oca/models/sendcloud_parcel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

from odoo import api, models


class SendcloudParcel(models.Model):
_inherit = "sendcloud.parcel"

@api.depends("company_id")
def _compute_brand_id(self):
res = super()._compute_brand_id()
for parcel in self:
brand = parcel.picking_id.sale_id.website_id.sendcloud_brand_id
if brand:
parcel.brand_id = brand
return res
11 changes: 11 additions & 0 deletions website_sendcloud_oca/models/website.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2025 Onestein (<https://www.onestein.nl>)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

from odoo import fields, models


class Website(models.Model):
_name = "website"
_inherit = ["website", "sendcloud.mixin"]

sendcloud_brand_id = fields.Many2one("sendcloud.brand")
3 changes: 3 additions & 0 deletions website_sendcloud_oca/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
10 changes: 10 additions & 0 deletions website_sendcloud_oca/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
This module is part of the Sendcloud connector for Odoo.

At the moment, the Sendcloud connector for Odoo consists of two modules:
delivery_sendcloud_oca and website_sendcloud_oca.

1) delivery_sendcloud_oca. This module works for the backend.
2) website_sendcloud_oca. This module is for the frontend (webshop) and
it depends on delivery_sendcloud_oca.

Full documentation for developers is in <https://docs.sendcloud.sc/>.
Loading